From 15871c9f6b54631b143f13e606b0d0833704886a Mon Sep 17 00:00:00 2001 From: achmizs <1874748+achmizs@users.noreply.github.com> Date: Sat, 11 Dec 2021 20:39:11 -0500 Subject: [PATCH] Initial commit --- gist-embed.php | 263 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 gist-embed.php diff --git a/gist-embed.php b/gist-embed.php new file mode 100644 index 0000000..d802b03 --- /dev/null +++ b/gist-embed.php @@ -0,0 +1,263 @@ + $line_range) { + if (preg_match("/([0-9]+)[-–]([0-9]+)/", $line_range, $m)) { + $line_numbers = array_merge($line_numbers, range(--$m[1],--$m[2])); + } else if (preg_match("/([0-9]+)[-–]$/", $line_range, $m)) { + $line_numbers[] = $to_end_from = --$m[1]; + } else { + $line_numbers[] = --$line_range; + } + } + + ## Same thing, but for highlighted line ranges. + $hl_line_ranges = $parsed['hl'] ? explode(',', $parsed['hl']) : array(); + $hl_line_numbers = array(); + $hl_to_end_from = -1; + foreach ($hl_line_ranges as $key => $hl_line_range) { + if (preg_match("/([0-9]+)[-–]([0-9]+)/", $hl_line_range, $m)) { + $hl_line_numbers = array_merge($hl_line_numbers, range(--$m[1],--$m[2])); + } else if (preg_match("/([0-9]+)[-–]$/", $hl_line_range, $m)) { + $hl_line_numbers[] = $hl_to_end_from = --$m[1]; + } else { + $hl_line_numbers[] = --$hl_line_range; + } + } + + $embed_js_url = "https://gist.github.com/$gist_id.js"; + $embed_raw_url = "https://gist.github.com/$gist_id/raw/"; + $embed_json_url = "https://gist.github.com/$gist_id.json"; + + $out = ""; + + if ($raw) { + ## If no filenames have been specified, we'll have to retrieve the file list from + ## the server; otherwise, we'll have no idea what files to request, and just + ## retrieving the 'raw' URL for a multi-file gist (with no file specified) gets + ## the first file only... + if (empty($files)) { + $full_gist_data = json_decode(file_get_contents($embed_json_url),true); + $files = $full_gist_data['files']; + } + + ## The raw text of each file of a multi-file gist must be retrieved individually. + $out = array(); + foreach ($files as $filename) { + $raw_text = file_get_contents($embed_raw_url.$filename); + if (!$raw_text) return Keep(""); + + $raw_lines = explode("\n", $raw_text); + ## Convert HTML entities. + if (!$noPre) { + foreach ($raw_lines as $line) + $line = PVSE($line); + } + ## Highlighting only works if no-pre is NOT enabled AND if we're displaying a + ## single file only. + if (!empty($hl_line_numbers) && !$noPre && count($files) == 1) { + if ($hl_to_end_from >= 0) + $hl_line_numbers = array_merge($hl_line_numbers, range($hl_to_end_from, count($raw_lines) - 1)); + foreach ($hl_line_numbers as $l) { + $raw_lines[$l] = ""; + } + } + ## Specifying line numbers only works if we're displaying a single file only. + if (!empty($line_numbers) && count($files) == 1) { + if ($to_end_from >= 0) + $line_numbers = array_merge($line_numbers, range($to_end_from, count($raw_lines) - 1)); + $raw_lines = array_intersect_key($raw_lines, array_flip($line_numbers)); + } + $raw_text = implode("\n", $raw_lines); + + ## The 'no-pre' option means we shouldn't wrap the text in a
tag.
+ $out[] = $noPre ? $raw_text : Keep("\n" . $raw_text . "\n
\n");
+ }
+ $out = implode($noPre ? "\n\n" : "", $out);
+ } else if ($noJS) {
+ include_once('simple_html_dom.php');
+
+ $json_content = json_decode(file_get_contents($embed_json_url),true);
+
+ ## The style sheet.
+ global $HTMLHeaderFmt;
+ $HTMLHeaderFmt[] = "\n";
+
+ ## The HTML.
+ $content_html = str_get_html(stripcslashes($json_content['div']));
+ $content = $content_html->find("div.gist", 0);
+ $content->id = "gistEmbed_$id";
+
+ ## If specific files are specified, we simply delete the div.gist-file containers
+ ## that contain files we don't want.
+ if (!empty($files)) {
+ $file_ids = preg_replace("/\./", "-", $files);
+ $gist_file_blocks = $content_html->find("div.gist-file");
+ foreach ($gist_file_blocks as $gist_file_block) {
+ if (!in_array(substr($gist_file_block->find("div.file", 0)->id, 5), $file_ids))
+ $gist_file_block->outertext = '';
+ }
+ }
+
+ ## Specifying line numbers only works if we're displaying a single file only.
+ $displayed_gist_files = array_filter($content_html->find("div.gist-file"), function ($d) { return $d->outertext; });
+ if (!empty($line_numbers) && count($displayed_gist_files) == 1) {
+ $lines = reset($displayed_gist_files)->find(".js-file-line-container tr");
+ if ($to_end_from >= 0)
+ $line_numbers = array_merge($line_numbers, range($to_end_from, count($lines) - 1));
+ foreach ($lines as $l) {
+ $line_num =$l->childNodes(0)->getAttribute('data-line-number');
+ if (!in_array(--$line_num, $line_numbers))
+ $l->outertext = '';
+ }
+ }
+
+ ## Highlighting specific line numbers only works if we're display a single file
+ ## only.
+ if (!empty($hl_line_numbers) && count($displayed_gist_files) == 1) {
+ $lines = reset($displayed_gist_files)->find(".js-file-line-container tr");
+ if ($hl_to_end_from >= 0)
+ $hl_line_numbers = array_merge($hl_line_numbers, range($hl_to_end_from, count($lines) - 1));
+ foreach ($lines as $i => $line) {
+ if (in_array($i, $hl_line_numbers)) {
+ $line->children(1)->class .= " gist-embed-highlighted-line";
+ }
+ }
+ }
+
+ $out = Keep($content);
+ } else {
+ $out = Keep("");
+
+ ## If specific files are specified, we'll delete the div.gist-file containers
+ ## that contain files we don't want (this script will run right after the script
+ ## that adds the content in the first place).
+ if (!empty($files)) {
+ $files_js = preg_replace("/\./", "-", "[ '".implode("', '",$files)."' ]");
+ $out .= Keep("
+
+ ");
+ }
+
+ ## Specifying line numbers only works if we're displaying a single file only.
+ if (!empty($line_numbers) || !empty($hl_line_numbers)) {
+ $line_numbers_js = "[ ".implode(", ",$line_numbers)." ]";
+ $hl_line_numbers_js = "[ ".implode(", ",$hl_line_numbers)." ]";
+ $out .= Keep("
+
+ ");
+ }
+
+ GistEmbedAppendFooter();
+ }
+
+ global $HTMLStylesFmt;
+ if (!$raw && $noFooter) {
+ $HTMLStylesFmt['gist-embed'][] = "#gistEmbed_$id .gist-meta { display: none; }\n";
+ $HTMLStylesFmt['gist-embed'][] = "#gistEmbed_$id .gist-data { border-bottom: none; border-radius: 2px; }\n";
+ }
+ if (!$raw && $noLineNumbers) {
+ $HTMLStylesFmt['gist-embed'][] = "#gistEmbed_$id td.js-line-number { display: none; }\n";
+ }
+
+ GistEmbedInjectStyles();
+
+ $id++;
+ return $out;
+}
+
+function GistEmbedAppendFooter() {
+ static $ran_once = false;
+ if (!$ran_once) {
+ global $HTMLFooterFmt;
+ $HTMLFooterFmt[] =
+"\n";
+ }
+ $ran_once = true;
+}
+
+function GistEmbedInjectStyles() {
+ static $ran_once = false;
+ if (!$ran_once) {
+ global $HTMLStylesFmt, $GistEmbedHighlightStyle;
+ $styles = "
+.gistRaw .gist-embed-highlighted-line { $GistEmbedHighlightStyle display: inline-block; width: calc(100% + 4px); padding-left: 4px; margin-left: -4px; }
+.gist tr .gist-embed-highlighted-line { $GistEmbedHighlightStyle }
+";
+ $HTMLStylesFmt['gist-embed'][] = $styles;
+ }
+ $ran_once = true;
+}