mirror of
https://github.com/zulip/zulip.git
synced 2025-10-22 20:42:14 +00:00
typeahead: Replace code block language hint text with more clear options
This commit - Replace the blank option with an italicized option that's the current default language, if there is one selected with "default" label. - Make the "text" option more informative by adding (no highlighting) to the label. - Remove the hint for "text". - Prioritize as left to right, before start typing: blank/default language, text, quote, spoiler, math, everything else... fixes: #33682
This commit is contained in:
@@ -6,6 +6,7 @@ from pygments.lexers import get_all_lexers
|
||||
|
||||
ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../")
|
||||
# The current priorities data set is based on StackOverflow's 2020 survey.
|
||||
# We also prioritize text, quote, math, spoiler over others to enhance UX.
|
||||
DATA_PATH = os.path.join(ZULIP_PATH, "tools", "setup", "lang.json")
|
||||
OUT_PATH = os.path.join(ZULIP_PATH, "web", "generated", "pygments_data.json")
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"default": {
|
||||
"text": 31,
|
||||
"javascript": 27,
|
||||
"python": 26,
|
||||
"java": 25,
|
||||
@@ -30,9 +31,9 @@
|
||||
},
|
||||
"custom": {
|
||||
"latex": 10,
|
||||
"math": 5,
|
||||
"quote": 5,
|
||||
"spoiler": 5
|
||||
"math": 28,
|
||||
"quote": 30,
|
||||
"spoiler": 29
|
||||
},
|
||||
"aliases": {
|
||||
"js": 27,
|
||||
|
@@ -843,11 +843,12 @@ export function get_candidates(
|
||||
}
|
||||
completing = "syntax";
|
||||
token = current_token;
|
||||
// If the code formatting button was triggered, we want to show a blank option
|
||||
// to improve the discoverability of the possibility of specifying a language.
|
||||
const language_list = compose_ui.code_formatting_button_triggered
|
||||
? ["", ...realm_playground.get_pygments_typeahead_list_for_composebox()]
|
||||
: realm_playground.get_pygments_typeahead_list_for_composebox();
|
||||
|
||||
const default_language = realm.realm_default_code_block_language;
|
||||
const language_list = realm_playground.get_pygments_typeahead_list_for_composebox();
|
||||
if (default_language) {
|
||||
language_list.unshift(default_language);
|
||||
}
|
||||
compose_ui.set_code_formatting_button_triggered(false);
|
||||
const matcher = get_language_matcher(token);
|
||||
const matches = language_list.filter((item) => matcher(item));
|
||||
@@ -1109,7 +1110,12 @@ export function content_highlighter_html(item: TypeaheadSuggestion): string | un
|
||||
case "stream":
|
||||
return typeahead_helper.render_stream(item);
|
||||
case "syntax":
|
||||
return typeahead_helper.render_typeahead_item({primary: item.language});
|
||||
return typeahead_helper.render_typeahead_item({
|
||||
primary: item.language,
|
||||
is_default_language:
|
||||
item.language !== "" &&
|
||||
item.language === realm.realm_default_code_block_language,
|
||||
});
|
||||
case "topic_jump":
|
||||
return typeahead_helper.render_typeahead_item({primary: item.message});
|
||||
case "topic_list": {
|
||||
@@ -1415,15 +1421,6 @@ function get_footer_html(): string | false {
|
||||
case "silent_mention":
|
||||
tip_text = $t({defaultMessage: "This silent mention won't trigger notifications."});
|
||||
break;
|
||||
case "syntax":
|
||||
if (realm.realm_default_code_block_language !== "") {
|
||||
tip_text = $t(
|
||||
{defaultMessage: "Default is {language}. Use 'text' to disable highlighting."},
|
||||
{language: realm.realm_default_code_block_language},
|
||||
);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1465,6 +1462,15 @@ export function initialize_compose_typeahead($element: JQuery<HTMLTextAreaElemen
|
||||
if (item.is_new_topic) {
|
||||
return `<em>${$t({defaultMessage: "New"})}</em>`;
|
||||
}
|
||||
} else if (item.type === "syntax") {
|
||||
if (
|
||||
item.language !== "" &&
|
||||
item.language === realm.realm_default_code_block_language
|
||||
) {
|
||||
return `<em>${$t({defaultMessage: "(default)"})}</em>`;
|
||||
} else if (item.language === "text") {
|
||||
return `<em>${$t({defaultMessage: "(no highlighting)"})}</em>`;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
@@ -113,6 +113,7 @@ export let render_typeahead_item = (args: {
|
||||
topic_object?: TopicSuggestion;
|
||||
is_stream_topic?: boolean;
|
||||
is_empty_string_topic?: boolean;
|
||||
is_default_language?: boolean;
|
||||
}): string => {
|
||||
const has_image = args.img_src !== undefined;
|
||||
const has_status = args.status_emoji_info !== undefined;
|
||||
@@ -434,8 +435,15 @@ function retain_unique_language_aliases(matches: string[]): string[] {
|
||||
|
||||
export function sort_languages(matches: LanguageSuggestion[], query: string): LanguageSuggestion[] {
|
||||
const languages = matches.map((object) => object.language);
|
||||
const default_language = realm.realm_default_code_block_language;
|
||||
const results = typeahead.triage(query, languages, (x) => x, compare_language);
|
||||
const unique_languages = retain_unique_language_aliases([...results.matches, ...results.rest]);
|
||||
let language_results;
|
||||
if (default_language && results.matches.includes(default_language)) {
|
||||
language_results = [default_language, ...results.matches, ...results.rest];
|
||||
} else {
|
||||
language_results = [...results.matches, ...results.rest];
|
||||
}
|
||||
const unique_languages = retain_unique_language_aliases(language_results);
|
||||
return unique_languages.map((language) => ({
|
||||
language,
|
||||
type: "syntax",
|
||||
|
@@ -2349,6 +2349,7 @@ body:not(.spectator-view) {
|
||||
}
|
||||
}
|
||||
|
||||
.default-language-display,
|
||||
.empty-topic-display,
|
||||
.empty-topic-placeholder-display::placeholder {
|
||||
font-style: italic;
|
||||
|
@@ -26,7 +26,7 @@
|
||||
{{else}}
|
||||
{{!-- Separate container to ensure overflowing text remains in this container. --}}
|
||||
<div class="typeahead-text-container{{#if has_secondary_html}} has_secondary_html{{/if}}">
|
||||
<strong class="typeahead-strong-section{{#if is_empty_string_topic}} empty-topic-display{{/if}}">
|
||||
<strong class="typeahead-strong-section{{#if is_empty_string_topic}} empty-topic-display{{/if}}{{#if is_default_language}} default-language-display{{/if}}">
|
||||
{{~#if stream~}}
|
||||
{{~> inline_decorated_channel_name stream=stream ~}}
|
||||
{{~else~}}
|
||||
|
@@ -2306,7 +2306,10 @@ test("content_highlighter_html", ({override_rewire}) => {
|
||||
ct.get_or_set_completing_for_tests("syntax");
|
||||
th_render_typeahead_item_called = false;
|
||||
override_rewire(typeahead_helper, "render_typeahead_item", (item) => {
|
||||
assert.deepEqual(item, {primary: "py"});
|
||||
assert.deepEqual(item, {
|
||||
is_default_language: false,
|
||||
primary: "py",
|
||||
});
|
||||
th_render_typeahead_item_called = true;
|
||||
});
|
||||
ct.content_highlighter_html({type: "syntax", language: "py"});
|
||||
|
@@ -78,6 +78,10 @@ run_test("get_pygments_typeahead_list_for_settings", () => {
|
||||
let iterator = candidates.entries();
|
||||
assert.equal(iterator.next().value[1], $t({defaultMessage: "Custom language: custom_lang"}));
|
||||
assert.equal(iterator.next().value[1], $t({defaultMessage: "Custom language: invent_a_lang"}));
|
||||
assert.equal(iterator.next().value[1], "Text only (text, text)");
|
||||
assert.equal(iterator.next().value[1], "quote (quote, quote)");
|
||||
assert.equal(iterator.next().value[1], "spoiler (spoiler, spoiler)");
|
||||
assert.equal(iterator.next().value[1], "math (math, math)");
|
||||
assert.equal(iterator.next().value[1], "JavaScript (javascript, js, javascript, js)");
|
||||
assert.equal(
|
||||
iterator.next().value[1],
|
||||
@@ -96,6 +100,10 @@ run_test("get_pygments_typeahead_list_for_settings", () => {
|
||||
);
|
||||
assert.equal(iterator.next().value[1], $t({defaultMessage: "Custom language: custom_lang"}));
|
||||
assert.equal(iterator.next().value[1], $t({defaultMessage: "Custom language: invent_a_lang"}));
|
||||
assert.equal(iterator.next().value[1], "Text only (text, text)");
|
||||
assert.equal(iterator.next().value[1], "quote (quote, quote)");
|
||||
assert.equal(iterator.next().value[1], "spoiler (spoiler, spoiler)");
|
||||
assert.equal(iterator.next().value[1], "math (math, math)");
|
||||
assert.equal(iterator.next().value[1], "JavaScript (javascript, js, javascript, js)");
|
||||
assert.equal(
|
||||
iterator.next().value[1],
|
||||
@@ -107,9 +115,7 @@ run_test("get_pygments_typeahead_list_for_settings", () => {
|
||||
iterator = candidates.entries();
|
||||
assert.equal(iterator.next().value[1], $t({defaultMessage: "Custom language: invent_a_lang"}));
|
||||
assert.equal(iterator.next().value[1], $t({defaultMessage: "Custom language: custom_lang"}));
|
||||
assert.equal(iterator.next().value[1], "JavaScript (javascript, js, javascript, js)");
|
||||
assert.equal(
|
||||
iterator.next().value[1],
|
||||
"Python (python, bazel, py, py3, pyi, python3, sage, starlark, python, bazel, py, py3, pyi, python3, sage, starlark)",
|
||||
);
|
||||
assert.equal(iterator.next().value[1], "Text only (text, text)");
|
||||
assert.equal(iterator.next().value[1], "quote (quote, quote)");
|
||||
assert.equal(iterator.next().value[1], "spoiler (spoiler, spoiler)");
|
||||
});
|
||||
|
@@ -394,12 +394,15 @@ test("sort_streams", ({override, override_rewire}) => {
|
||||
|
||||
function language_items(languages) {
|
||||
return languages.map((language) => ({
|
||||
type: "syntax",
|
||||
language,
|
||||
type: "syntax",
|
||||
}));
|
||||
}
|
||||
|
||||
test("sort_languages", ({override_rewire}) => {
|
||||
test("sort_languages", ({override, override_rewire}) => {
|
||||
override(realm, "realm_default_code_block_language", "dart");
|
||||
const default_language = realm.realm_default_code_block_language;
|
||||
|
||||
override_rewire(pygments_data, "langs", {
|
||||
python: {priority: 26},
|
||||
javascript: {priority: 27},
|
||||
@@ -407,20 +410,52 @@ test("sort_languages", ({override_rewire}) => {
|
||||
pascal: {priority: 15},
|
||||
perl: {priority: 3},
|
||||
css: {priority: 21},
|
||||
spoiler: {priority: 29},
|
||||
text: {priority: 31},
|
||||
quote: {priority: 30},
|
||||
math: {priority: 28},
|
||||
});
|
||||
|
||||
let test_langs = language_items(["pascal", "perl", "php", "python", "javascript"]);
|
||||
let test_langs = language_items(["pascal", "perl", "php", "python", "spoiler", "javascript"]);
|
||||
test_langs = th.sort_languages(test_langs, "p");
|
||||
|
||||
// Sort languages by matching first letter, and then by popularity
|
||||
assert.deepEqual(test_langs, language_items(["python", "php", "pascal", "perl", "javascript"]));
|
||||
assert.deepEqual(
|
||||
test_langs,
|
||||
language_items(["python", "php", "pascal", "perl", "spoiler", "javascript"]),
|
||||
);
|
||||
|
||||
// Test if popularity between two languages are the same
|
||||
pygments_data.langs.php = {priority: 26};
|
||||
test_langs = language_items(["pascal", "perl", "php", "python", "javascript"]);
|
||||
test_langs = language_items(["pascal", "perl", "php", "python", "spoiler", "javascript"]);
|
||||
test_langs = th.sort_languages(test_langs, "p");
|
||||
|
||||
assert.deepEqual(test_langs, language_items(["php", "python", "pascal", "perl", "javascript"]));
|
||||
assert.deepEqual(
|
||||
test_langs,
|
||||
language_items(["php", "python", "pascal", "perl", "spoiler", "javascript"]),
|
||||
);
|
||||
|
||||
test_langs = language_items([
|
||||
default_language,
|
||||
"text",
|
||||
"quote",
|
||||
"math",
|
||||
"python",
|
||||
"javascript",
|
||||
]);
|
||||
const test_langs_for_default = th.sort_languages(test_langs, "d");
|
||||
|
||||
assert.deepEqual(
|
||||
test_langs_for_default,
|
||||
language_items([default_language, "text", "quote", "math", "javascript", "python"]),
|
||||
);
|
||||
|
||||
test_langs = th.sort_languages(test_langs, "t");
|
||||
|
||||
assert.deepEqual(
|
||||
test_langs,
|
||||
language_items(["text", "quote", "math", "javascript", "python", default_language]),
|
||||
);
|
||||
});
|
||||
|
||||
test("sort_languages on actual data", () => {
|
||||
|
Reference in New Issue
Block a user