From a257acec6da0c2f3a03e8ac167f486eb3789dbbf Mon Sep 17 00:00:00 2001 From: 420tushar Date: Sat, 15 Aug 2020 17:10:47 +0530 Subject: [PATCH] Create tush-app.js --- web/dist/js/tush-app.js | 1028 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1028 insertions(+) create mode 100644 web/dist/js/tush-app.js diff --git a/web/dist/js/tush-app.js b/web/dist/js/tush-app.js new file mode 100644 index 0000000..1f471b7 --- /dev/null +++ b/web/dist/js/tush-app.js @@ -0,0 +1,1028 @@ +// Load the necessary static in the head and code from https://github.com/420tushar/letmetest +document.write(''); +// markdown支持 +document.write(''); +document.write(''); +// add custome theme and darkmode +if (UI.dark_mode) { + document.write(``); +} + +// Initialize the page and load the necessary resources +function init() { + document.siteName = $('title').html(); + $('body').addClass(`mdui-theme-primary-${UI.main_color} mdui-theme-accent-${UI.accent_color}`); + var html = ` +
+ +
+
+
+ `; + $('body').html(html); +} + +const Os = { + isWindows: navigator.platform.toUpperCase().indexOf('WIN') > -1, // .includes + isMac: navigator.platform.toUpperCase().indexOf('MAC') > -1, + isMacLike: /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform), + isIos: /(iPhone|iPod|iPad)/i.test(navigator.platform), + isMobile: /Android|webOS|iPhone|iPad|iPod|iOS|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) +}; + +function getDocumentHeight() { + var D = document; + return Math.max( + D.body.scrollHeight, D.documentElement.scrollHeight, + D.body.offsetHeight, D.documentElement.offsetHeight, + D.body.clientHeight, D.documentElement.clientHeight + ); +} + +function render(path) { + if (path.indexOf("?") > 0) { + path = path.substr(0, path.indexOf("?")); + } + title(path); + nav(path); + // .../0: This + var reg = /\/\d+:$/g; + if (window.MODEL.is_search_page) { + // Used to store the state of some scroll events + window.scroll_status = { + // Whether the scroll event is bound + event_bound: false, + // "Scroll to the bottom, loading more data" event lock + loading_lock: false + }; + render_search_result_list() + } else if (path.match(reg) || path.substr(-1) == '/') { + // Used to store the state of some scroll events + window.scroll_status = { + // Whether the scroll event is bound + event_bound: false, + // "Scroll to the bottom, loading more data" event lock + loading_lock: false + }; + list(path); + } else { + file(path); + } +} + + +// Render title +function title(path) { + path = decodeURI(path); + var cur = window.current_drive_order || 0; + var drive_name = window.drive_names[cur]; + path = path.replace(`/${cur}:`, ''); + // $('title').html(document.siteName + ' - ' + path); + var model = window.MODEL; + if (model.is_search_page) + $('title').html(`${document.siteName} - ${drive_name} - Search results for ${model.q} `); + else + $('title').html(`${document.siteName} - ${drive_name} - ${path}`); +} + +// Render the navigation bar +function nav(path) { + var model = window.MODEL; + var html = ""; + var cur = window.current_drive_order || 0; + html += `${document.siteName}`; + var names = window.drive_names; + /*html += ``; + html += ``;*/ + + // Change to select + html += ``; + + if (!model.is_search_page) { + var arr = path.trim('/').split('/'); + var p = '/'; + if (arr.length > 1) { + arr.shift(); + for (i in arr) { + var n = arr[i]; + n = decodeURI(n); + p += n + '/'; + if (n == '') { + break; + } + html += `chevron_right${n}`; + } + } + } + var search_text = model.is_search_page ? (model.q || '') : ''; + const isMobile = Os.isMobile; + var search_bar = `
+ `; + + // Personal or team + if (model.root_type < 2) { + // Show search box + html += search_bar; + } + + $('#nav').html(html); + mdui.mutation(); + mdui.updateTextFields(); +} + +/** + * Initiate POST request for listing + * @param path Path + * @param params Form params + * @param resultCallback Success Result Callback + * @param authErrorCallback Pass Error Callback + */ +function requestListPath(path, params, resultCallback, authErrorCallback) { + var p = { + password: params['password'] || null, + page_token: params['page_token'] || null, + page_index: params['page_index'] || 0 + }; + $.post(path, p, function (data, status) { + var res = jQuery.parseJSON(data); + if (res && res.error && res.error.code == '401') { + // Password verification failed + if (authErrorCallback) authErrorCallback(path) + } else if (res && res.data) { + if (resultCallback) resultCallback(res, path, p) + } + }) +} + +/** + * Search POST request + * @param params Form params + * @param resultCallback Success callback + */ +function requestSearch(params, resultCallback) { + var p = { + q: params['q'] || null, + page_token: params['page_token'] || null, + page_index: params['page_index'] || 0 + }; + $.post(`/${window.current_drive_order}:search`, p, function (data, status) { + var res = jQuery.parseJSON(data); + if (res && res.data) { + if (resultCallback) resultCallback(res, p) + } + }) +} + + +// Render file list +function list(path) { + var content = ` + +
+ +
+
+ +
Total item
+
+ + `; + $('#content').html(content); + + var password = localStorage.getItem('password' + path); + $('#list').html(`
`); + $('#readme_md').hide().html(''); + $('#head_md').hide().html(''); + + /** + * Callback after the column list request successfully returns data + * The result returned by @param res (object) + * @param path the requested path + * @param prevReqParams parameters used in request + */ + function successResultCallback(res, path, prevReqParams) { + + // Temporarily store nextPageToken and currentPageIndex in the list element + $('#list') + .data('nextPageToken', res['nextPageToken']) + .data('curPageIndex', res['curPageIndex']); + + // Remove loading spinner + $('#spinner').remove(); + + if (res['nextPageToken'] === null) { + // If it is the last page, unbind the scroll event, reset scroll_status, and append the data + $(window).off('scroll'); + window.scroll_status.event_bound = false; + window.scroll_status.loading_lock = false; + append_files_to_list(path, res['data']['files']); + } else { + // If it is not the last page, append data and bind the scroll event (if not already bound), update scroll_status + append_files_to_list(path, res['data']['files']); + if (window.scroll_status.event_bound !== true) { + // Bind event, if not yet bound + $(window).on('scroll', function () { + var scrollTop = $(this).scrollTop(); + var scrollHeight = getDocumentHeight(); + var windowHeight = $(this).height(); + // Roll to the bottom + if (scrollTop + windowHeight > scrollHeight - (Os.isMobile ? 130 : 80)) { + /* + When the event of scrolling to the bottom is triggered, if it is already loading at this time, the event is ignored; + Otherwise, go to loading and occupy the loading lock, indicating that loading is in progress + */ + if (window.scroll_status.loading_lock === true) { + return; + } + window.scroll_status.loading_lock = true; + + // Show a loading spinner + $(`
`) + .insertBefore('#readme_md'); + mdui.updateSpinners(); + // mdui.mutation(); + + let $list = $('#list'); + requestListPath(path, { + password: prevReqParams['password'], + page_token: $list.data('nextPageToken'), + // Request next page + page_index: $list.data('curPageIndex') + 1 + }, + successResultCallback, + // The password is the same as before. No authError + null + ) + } + }); + window.scroll_status.event_bound = true + } + } + + // After loading successfully and rendering new data successfully, release the loading lock so that you can continue to process the "scroll to bottom" event + if (window.scroll_status.loading_lock === true) { + window.scroll_status.loading_lock = false + } + } + + // Start requesting data from page 1 + requestListPath(path, {password: password}, + successResultCallback, + function (path) { + $('#spinner').remove(); + var pass = prompt("Directory encryption, please enter the password", ""); + localStorage.setItem('password' + path, pass); + if (pass != null && pass != "") { + list(path); + } else { + history.go(-1); + } + }); +} + +/** + * Append the data of the requested new page to the list + * @param path + * @param files request result + */ +function append_files_to_list(path, files) { + var $list = $('#list'); + // Is it the last page of data? + var is_lastpage_loaded = null === $list.data('nextPageToken'); + var is_firstpage = '0' == $list.data('curPageIndex'); + + html = ""; + let targetFiles = []; + for (i in files) { + var item = files[i]; + var p = path + item.name + '/'; + if (item['size'] == undefined) { + item['size'] = ""; + } + + item['modifiedTime'] = utc2beijing(item['modifiedTime']); + item['size'] = formatFileSize(item['size']); + if (item['mimeType'] == 'application/vnd.google-apps.folder') { + html += `
  • +
    + folder_open + ${item.name} +
    +
    ${item['modifiedTime']}
    +
    ${item['size']}
    +
    +
  • `; + } else { + var p = path + item.name; + const filepath = path + item.name; + var c = "file"; + // README is displayed after the last page is loaded, otherwise it will affect the scroll event + if (is_lastpage_loaded && item.name == "README.md") { + get_file(p, item, function (data) { + markdown("#readme_md", data); + }); + } + if (item.name == "HEAD.md") { + get_file(p, item, function (data) { + markdown("#head_md", data); + }); + } + var ext = p.split('.').pop().toLowerCase(); + if ("|html|php|css|go|java|js|json|txt|sh|md|mp4|webm|avi|bmp|jpg|jpeg|png|gif|m4a|mp3|flac|wav|ogg|mpg|mpeg|mkv|rm|rmvb|mov|wmv|asf|ts|flv|pdf|".indexOf(`|${ext}|`) >= 0) { + targetFiles.push(filepath); + p += "?a=view"; + c += " view"; + } + html += `
  • +
    + insert_drive_file + ${item.name} +
    +
    ${item['modifiedTime']}
    +
    ${item['size']}
    +
    +
  • `; + } + } + + /*let targetObj = {}; + targetFiles.forEach((myFilepath, myIndex) => { + if (!targetObj[myFilepath]) { + targetObj[myFilepath] = { + filepath: myFilepath, + prev: myIndex === 0 ? null : targetFiles[myIndex - 1], + next: myIndex === targetFiles.length - 1 ? null : targetFiles[myIndex + 1], + } + } + }) + // console.log(targetObj) + if (Object.keys(targetObj).length) { + localStorage.setItem(path, JSON.stringify(targetObj)); + // console.log(path) + }*/ + + if (targetFiles.length > 0) { + let old = localStorage.getItem(path); + let new_children = targetFiles; + // Reset on page 1; otherwise append + if (!is_firstpage && old) { + let old_children; + try { + old_children = JSON.parse(old); + if (!Array.isArray(old_children)) { + old_children = [] + } + } catch (e) { + old_children = []; + } + new_children = old_children.concat(targetFiles) + } + + localStorage.setItem(path, JSON.stringify(new_children)) + } + + // When it is page 1, remove the horizontal loading bar + $list.html(($list.data('curPageIndex') == '0' ? '' : $list.html()) + html); + // When it is the last page, count and display the total number of items + if (is_lastpage_loaded) { + $('#count').removeClass('mdui-hidden').find('.number').text($list.find('li.mdui-list-item').length); + } +} + +/** + * Render the search results list. There is a lot of repetitive code, but there are different logics in it. + */ +function render_search_result_list() { + var content = ` + +
    + +
    +
    + +
    Total item
    +
    + + `; + $('#content').html(content); + + $('#list').html(`
    `); + $('#readme_md').hide().html(''); + $('#head_md').hide().html(''); + + /** + * Callback after successful search request returns data + * The result returned by @param res (object) + * @param path the requested path + * @param prevReqParams parameters used in request + */ + function searchSuccessCallback(res, prevReqParams) { + + // Temporarily store nextPageToken and currentPageIndex in the list element + $('#list') + .data('nextPageToken', res['nextPageToken']) + .data('curPageIndex', res['curPageIndex']); + + // Remove loading spinner + $('#spinner').remove(); + + if (res['nextPageToken'] === null) { + // If it is the last page, unbind the scroll event, reset scroll_status, and append the data + $(window).off('scroll'); + window.scroll_status.event_bound = false; + window.scroll_status.loading_lock = false; + append_search_result_to_list(res['data']['files']); + } else { + // If it is not the last page, append data and bind the scroll event (if not already bound), update scroll_status + append_search_result_to_list(res['data']['files']); + if (window.scroll_status.event_bound !== true) { + // Bind event, if not yet bound + $(window).on('scroll', function () { + var scrollTop = $(this).scrollTop(); + var scrollHeight = getDocumentHeight(); + var windowHeight = $(this).height(); + // Roll to the bottom + if (scrollTop + windowHeight > scrollHeight - (Os.isMobile ? 130 : 80)) { + /* + When the event of scrolling to the bottom is triggered, if it is already loading at this time, the event is ignored; + Otherwise, go to loading and occupy the loading lock, indicating that loading is in progress + */ + if (window.scroll_status.loading_lock === true) { + return; + } + window.scroll_status.loading_lock = true; + + // Show a loading spinner + $(`
    `) + .insertBefore('#readme_md'); + mdui.updateSpinners(); + // mdui.mutation(); + + let $list = $('#list'); + requestSearch({ + q: window.MODEL.q, + page_token: $list.data('nextPageToken'), + // Request next page + page_index: $list.data('curPageIndex') + 1 + }, + searchSuccessCallback + ) + } + }); + window.scroll_status.event_bound = true + } + } + + // After loading successfully and rendering new data successfully, release the loading lock so that you can continue to process the "scroll to bottom" event + if (window.scroll_status.loading_lock === true) { + window.scroll_status.loading_lock = false + } + } + + // Start requesting data from page 1 + requestSearch({q: window.MODEL.q}, searchSuccessCallback); +} + +/** + * Append a new page of search results + * @param files + */ +function append_search_result_to_list(files) { + var $list = $('#list'); + // Is it the last page of data? + var is_lastpage_loaded = null === $list.data('nextPageToken'); + // var is_firstpage = '0' == $list.data('curPageIndex'); + + html = ""; + + for (i in files) { + var item = files[i]; + if (item['size'] == undefined) { + item['size'] = ""; + } + + item['modifiedTime'] = utc2beijing(item['modifiedTime']); + item['size'] = formatFileSize(item['size']); + if (item['mimeType'] == 'application/vnd.google-apps.folder') { + html += `
  • +
    + folder_open + ${item.name} +
    +
    ${item['modifiedTime']}
    +
    ${item['size']}
    +
    +
  • `; + } else { + var c = "file"; + var ext = item.name.split('.').pop().toLowerCase(); + if ("|html|php|css|go|java|js|json|txt|sh|md|mp4|webm|avi|bmp|jpg|jpeg|png|gif|m4a|mp3|flac|wav|ogg|mpg|mpeg|mkv|rm|rmvb|mov|wmv|asf|ts|flv|".indexOf(`|${ext}|`) >= 0) { + c += " view"; + } + html += `
  • +
    + insert_drive_file + ${item.name} +
    +
    ${item['modifiedTime']}
    +
    ${item['size']}
    +
    +
  • `; + } + } + + // When it is page 1, remove the horizontal loading bar + $list.html(($list.data('curPageIndex') == '0' ? '' : $list.html()) + html); + // When it is the last page, count and display the total number of items + if (is_lastpage_loaded) { + $('#count').removeClass('mdui-hidden').find('.number').text($list.find('li.mdui-list-item').length); + } +} + +/** + * Search result item click event + * @param a_ele Clicked element + */ +function onSearchResultItemClick(a_ele) { + var me = $(a_ele); + var can_preview = me.hasClass('view'); + var cur = window.current_drive_order; + var dialog = mdui.dialog({ + title: '', + content: '
    Getting target path...
    ', + // content: '
    ', + history: false, + modal: true, + closeOnEsc: true + }); + mdui.updateSpinners(); + + // Request a path + $.post(`/${cur}:id2path`, {id: a_ele.id}, function (data) { + if (data) { + dialog.close(); + var href = `/${cur}:${data}${can_preview ? '?a=view' : ''}`; + dialog = mdui.dialog({ + title: 'Target path', + content: `${data}`, + history: false, + modal: true, + closeOnEsc: true, + buttons: [ + { + text: 'turn on', onClick: function () { + window.location.href = href + } + }, { + text: 'Open in new tab', onClick: function () { + window.open(href) + } + } + , {text: 'cancel'} + ] + }); + return; + } + dialog.close(); + dialog = mdui.dialog({ + title: ' Failed to get the target path', + content: 'It may be because this item does not exist in the disc! It may also be because the file [Shared with me] has not been added to Personal Drive!', + history: false, + modal: true, + closeOnEsc: true, + buttons: [ + {text: 'WTF ???'} + ] + }); + }) +} + +function get_file(path, file, callback) { + var key = "file_path_" + path + file['modifiedTime']; + var data = localStorage.getItem(key); + if (data != undefined) { + return callback(data); + } else { + $.get(path, function (d) { + localStorage.setItem(key, d); + callback(d); + }); + } +} + + +// File display ?a=view +function file(path) { + var name = path.split('/').pop(); + var ext = name.split('.').pop().toLowerCase().replace(`?a=view`, "").toLowerCase(); + if ("|html|php|css|go|java|js|json|txt|sh|md|".indexOf(`|${ext}|`) >= 0) { + return file_code(path); + } + + if ("|mp4|webm|avi|".indexOf(`|${ext}|`) >= 0) { + return file_video(path); + } + + if ("|mpg|mpeg|mkv|rm|rmvb|mov|wmv|asf|ts|flv|".indexOf(`|${ext}|`) >= 0) { + return file_video(path); + } + + if ("|mp3|flac|wav|ogg|m4a|".indexOf(`|${ext}|`) >= 0) { + return file_audio(path); + } + + if ("|bmp|jpg|jpeg|png|gif|".indexOf(`|${ext}|`) >= 0) { + return file_image(path); + } + + if ('pdf' === ext) return file_pdf(path); +} + +// Document display |html|php|css|go|java|js|json|txt|sh|md| +function file_code(path) { + var type = { + "html": "html", + "php": "php", + "css": "css", + "go": "golang", + "java": "java", + "js": "javascript", + "json": "json", + "txt": "Text", + "sh": "sh", + "md": "Markdown", + }; + var name = path.split('/').pop(); + var ext = name.split('.').pop().toLowerCase(); + var href = window.location.origin + path; + var content = ` +
    +
    
    +
    +
    + + +
    +file_download + + + `; + $('#content').html(content); + + $.get(path, function (data) { + $('#editor').html($('
    ').text(data).html()); + var code_type = "Text"; + if (type[ext] != undefined) { + code_type = type[ext]; + } + var editor = ace.edit("editor"); + editor.setTheme("ace/theme/ambiance"); + editor.setFontSize(18); + editor.session.setMode("ace/mode/" + code_type); + + //Autocompletion + editor.setOptions({ + enableBasicAutocompletion: true, + enableSnippets: true, + enableLiveAutocompletion: true, + maxLines: Infinity + }); + }); +} + +function copyToClipboard(str) { + const $temp = $(""); + $("body").append($temp); + $temp.val(str).select(); + document.execCommand("copy"); + $temp.remove(); +} + +// Document display video |mp4|webm|avi| +function file_video(path) { + const url = window.location.origin + path; + let player_items = [ + { + text: 'MXPlayer(Free)', + href: `intent:${url}#Intent;package=com.mxtech.videoplayer.ad;S.title=${path};end`, + }, + { + text: 'MXPlayer(Pro)', + href: `intent:${url}#Intent;package=com.mxtech.videoplayer.pro;S.title=${path};end`, + }, + { + text: 'nPlayer', + href: `nplayer-${url}`, + }, + { + text: 'VLC', + href: `vlc://${url}`, + }, + { + text: 'PotPlayer', + href: `potplayer://${url}` + } + ] + .map(it => `
  • ${it.text}
  • `) + .join(''); + player_items += `
  • +
  • Copy Link
  • `; + const playBtn = ` + + `; + + const content = ` +
    +
    + +
    ${playBtn} + +
    + + +
    +
    + + +
    +
    +file_download + `; + $('#content').html(content); + $('#copy-link').on('click', () => { + copyToClipboard(url); + mdui.snackbar('Copied to clipboard!'); + }); +} + +// File display Audio |mp3|flac|m4a|wav|ogg| +function file_audio(path) { + var url = window.location.origin + path; + var content = ` +
    +
    + +
    + +
    + + +
    +
    + + +
    +
    +file_download + `; + $('#content').html(content); +} + +// Document display pdf pdf +function file_pdf(path) { + const url = window.location.origin + path; + const inline_url = `${url}?inline=true` + const file_name = decodeURI(path.slice(path.lastIndexOf('/') + 1, path.length)) + var content = ` + + file_download + `; + $('#content').removeClass('mdui-container').addClass('mdui-container-fluid').css({padding: 0}).html(content); +} + +// image display +function file_image(path) { + var url = window.location.origin + path; + // console.log(window.location.pathname) + const currentPathname = window.location.pathname + const lastIndex = currentPathname.lastIndexOf('/'); + const fatherPathname = currentPathname.slice(0, lastIndex + 1); + // console.log(fatherPathname) + let target_children = localStorage.getItem(fatherPathname); + // console.log(`fatherPathname: ${fatherPathname}`); + // console.log(target_children) + let targetText = ''; + if (target_children) { + try { + target_children = JSON.parse(target_children); + if (!Array.isArray(target_children)) { + target_children = [] + } + } catch (e) { + console.error(e); + target_children = []; + } + if (target_children.length > 0 && target_children.includes(path)) { + let len = target_children.length; + let cur = target_children.indexOf(path); + // console.log(`len = ${len}`) + // console.log(`cur = ${cur}`) + let prev_child = (cur - 1 > -1) ? target_children[cur - 1] : null; + let next_child = (cur + 1 < len) ? target_children[cur + 1] : null; + targetText = ` +
    +
    +
    + ${prev_child ? `` : ``} +
    +
    + ${next_child ? `` : ``} +
    +
    +
    + `; + } + //
    + // ${targetObj[path].prev ? `Prev` : `Prev`} + // ${targetObj[path].next ? `Next` : `Prev`} + //
    + } + var content = ` +
    +
    +
    + ${targetText} + +
    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +file_download + `; + // my code + $('#content').html(content); + $('#leftBtn, #rightBtn').click((e) => { + let target = $(e.target); + if (['I', 'SPAN'].includes(e.target.nodeName)) { + target = $(e.target).parent(); + } + const filepath = target.attr('data-filepath'); + const direction = target.attr('data-direction'); + //console.log(`${direction}Turn page ${filepath}`); + file(filepath) + }); +} + + +// Time conversion +function utc2beijing(utc_datetime) { + // Convert to normal time format year-month-day hour: minute: second + var T_pos = utc_datetime.indexOf('T'); + var Z_pos = utc_datetime.indexOf('Z'); + var year_month_day = utc_datetime.substr(0, T_pos); + var hour_minute_second = utc_datetime.substr(T_pos + 1, Z_pos - T_pos - 1); + var new_datetime = year_month_day + " " + hour_minute_second; // 2017-03-31 08:02:06 + + // Processing becomes timestamp + timestamp = new Date(Date.parse(new_datetime)); + timestamp = timestamp.getTime(); + timestamp = timestamp / 1000; + + // 8 hours increase, Beijing time is eight more time zones than UTC time + var unixtimestamp = timestamp + 5.5 * 60 * 60; + + // Timestamp to time + var unixtimestamp = new Date(unixtimestamp * 1000); + var year = 1900 + unixtimestamp.getYear(); + var month = "0" + (unixtimestamp.getMonth() + 1); + var date = "0" + unixtimestamp.getDate(); + var hour = "0" + unixtimestamp.getHours(); + var minute = "0" + unixtimestamp.getMinutes(); + var second = "0" + unixtimestamp.getSeconds(); + return year + "-" + month.substring(month.length - 2, month.length) + "-" + date.substring(date.length - 2, date.length) + + " " + hour.substring(hour.length - 2, hour.length) + ":" + + minute.substring(minute.length - 2, minute.length) + ":" + + second.substring(second.length - 2, second.length); +} + +// bytes adaptive conversion to KB, MB, GB +function formatFileSize(bytes) { + if (bytes >= 1000000000) { + bytes = (bytes / 1000000000).toFixed(2) + ' GB'; + } else if (bytes >= 1000000) { + bytes = (bytes / 1000000).toFixed(2) + ' MB'; + } else if (bytes >= 1000) { + bytes = (bytes / 1000).toFixed(2) + ' KB'; + } else if (bytes > 1) { + bytes = bytes + ' bytes'; + } else if (bytes == 1) { + bytes = bytes + ' byte'; + } else { + bytes = ''; + } + return bytes; +} + +String.prototype.trim = function (char) { + if (char) { + return this.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), ''); + } + return this.replace(/^\s+|\s+$/g, ''); +}; + + +// README.md HEAD.md support +function markdown(el, data) { + if (window.md == undefined) { + //$.getScript('https://cdn.jsdelivr.net/npm/markdown-it@10.0.0/dist/markdown-it.min.js',function(){ + window.md = window.markdownit(); + markdown(el, data); + //}); + } else { + var html = md.render(data); + $(el).show().html(html); + } +} + +// Listen for fallback events +window.onpopstate = function () { + var path = window.location.pathname; + render(path); +} + + +$(function () { + init(); + var path = window.location.pathname; + /*$("body").on("click", '.folder', function () { + var url = $(this).attr('href'); + history.pushState(null, null, url); + render(url); + return false; + }); + $("body").on("click", '.view', function () { + var url = $(this).attr('href'); + history.pushState(null, null, url); + render(url); + return false; + });*/ + + render(path); +});