Skip to content

Dynamic play button based on no_run property and used crates availability #404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/theme/book.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ code {
.hidden {
display: none;
}
.play-button.hidden {
display: none;
}
h2,
h3 {
margin-top: 2.5em;
Expand Down
110 changes: 85 additions & 25 deletions src/theme/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $( document ).ready(function() {
tabReplace: ' ', // 4 spaces
languages: [], // Languages used for auto-detection
});

if (window.ace) {
// language-rust class needs to be removed for editable
// blocks or highlightjs will capture events
Expand All @@ -31,7 +31,7 @@ $( document ).ready(function() {
hljs.highlightBlock(block);
});
}

// Adding the hljs class gives code blocks the color css
// even if highlighting doesn't apply
$('code').addClass('hljs');
Expand Down Expand Up @@ -128,27 +128,27 @@ $( document ).ready(function() {

function set_theme(theme) {
let ace_theme;

if (theme == 'coal' || theme == 'navy') {
$("[href='ayu-highlight.css']").prop('disabled', true);
$("[href='tomorrow-night.css']").prop('disabled', false);
$("[href='highlight.css']").prop('disabled', true);

ace_theme = "ace/theme/tomorrow_night";
} else if (theme == 'ayu') {
$("[href='ayu-highlight.css']").prop('disabled', false);
$("[href='tomorrow-night.css']").prop('disabled', true);
$("[href='highlight.css']").prop('disabled', true);

ace_theme = "ace/theme/tomorrow_night";
} else {
$("[href='ayu-highlight.css']").prop('disabled', true);
$("[href='tomorrow-night.css']").prop('disabled', true);
$("[href='highlight.css']").prop('disabled', false);

ace_theme = "ace/theme/dawn";
}

if (window.ace && window.editors) {
window.editors.forEach(function(editor) {
editor.setTheme(ace_theme);
Expand Down Expand Up @@ -219,7 +219,7 @@ $( document ).ready(function() {
pre_block.prepend("<div class=\"buttons\"></div>");
buttons = pre_block.find(".buttons");
}
buttons.prepend("<i class=\"fa fa-play play-button\"></i>");
buttons.prepend("<i class=\"fa fa-play play-button hidden\"></i>");
buttons.prepend("<i class=\"fa fa-copy clip-button\"><i class=\"tooltiptext\"></i></i>");

let code_block = pre_block.find("code").first();
Expand All @@ -245,14 +245,7 @@ $( document ).ready(function() {
text: function(trigger) {
hideTooltip(trigger);
let playpen = $(trigger).parents(".playpen");
let code_block = playpen.find("code").first();

if (window.ace && code_block.hasClass("editable")) {
let editor = window.ace.edit(code_block.get(0));
return editor.getValue();
} else {
return code_block.get(0).textContent;
}
return playpen_text(playpen);
}
});
clipboardSnippets.on('success', function(e) {
Expand All @@ -262,8 +255,83 @@ $( document ).ready(function() {
clipboardSnippets.on('error', function(e) {
showTooltip(e.trigger, "Clipboard error!");
});

$.ajax({
url: "https://play.rust-lang.org/meta/crates",
method: "POST",
crossDomain: true,
dataType: "json",
contentType: "application/json",
success: function(response){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we do on error?

Copy link
Contributor Author

@budziq budziq Sep 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@azerupi

What do we do on error?

Currently nothing. The play buttons will not appear which imho is a safer default than showing play buttons on content that might be unsupported by play.rlo.
I did not have a reasonable fallback scenario, do you have anything in mind?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that is perfect 👍
Not showing the play button when the playground can not be reached makes a lot of sense :)

// get list of crates available in the rust playground
let playground_crates = response.crates.map(function(item) {return item["id"];} );
$(".playpen").each(function(block) {
handle_crate_list_update($(this), playground_crates);
});
},
});

});

function playpen_text(playpen) {
let code_block = playpen.find("code").first();

if (window.ace && code_block.hasClass("editable")) {
let editor = window.ace.edit(code_block.get(0));
return editor.getValue();
} else {
return code_block.get(0).textContent;
}
}

function handle_crate_list_update(playpen_block, playground_crates) {
// update the play buttons after receiving the response
update_play_button(playpen_block, playground_crates);

// and install on change listener to dynamically update ACE editors
if (window.ace) {
let code_block = playpen_block.find("code").first();
if (code_block.hasClass("editable")) {
let editor = window.ace.edit(code_block.get(0));
editor.on("change", function(e){
update_play_button(playpen_block, playground_crates);
});
}
}
}

// updates the visibility of play button based on `no_run` class and
// used crates vs ones available on http://play.rust-lang.org
function update_play_button(pre_block, playground_crates) {
var play_button = pre_block.find(".play-button");

var classes = pre_block.find("code").attr("class").split(" ");
// skip if code is `no_run`
if (classes.indexOf("no_run") > -1) {
play_button.addClass("hidden");
return;
}

// get list of `extern crate`'s from snippet
var txt = playpen_text(pre_block);
var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
var snippet_crates = [];
while (item = re.exec(txt)) {
snippet_crates.push(item[1]);
}

// check if all used crates are available on play.rust-lang.org
var all_available = snippet_crates.every(function(elem) {
return playground_crates.indexOf(elem) > -1;
});

if (all_available) {
play_button.removeClass("hidden");
} else {
play_button.addClass("hidden");
}
}

function hideTooltip(elem) {
elem.firstChild.innerText="";
elem.setAttribute('class', 'fa fa-copy clip-button');
Expand Down Expand Up @@ -300,15 +368,7 @@ function run_rust_code(code_block) {
result_block = code_block.find(".result");
}

let text;

let inner_code_block = code_block.find("code").first();
if (window.ace && inner_code_block.hasClass("editable")) {
let editor = window.ace.edit(inner_code_block.get(0));
text = editor.getValue();
} else {
text = inner_code_block.text();
}
let text = playpen_text(code_block);;

var params = {
version: "stable",
Expand Down
4 changes: 4 additions & 0 deletions src/theme/stylus/general.styl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ code {
display: none;
}

.play-button.hidden {
display: none;
}

h2, h3 { margin-top: 2.5em }
h4, h5 { margin-top: 2em }

Expand Down