您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
This tool shows tables on database problems after you submit a wrong answer, so you don't need to read their unreadable JSON representation of tables.
当前为
// ==UserScript== // @name Tool for leetcode.com // @match https://leetcode.com/problems/* // @match https://leetcode.com/submissions/detail/* // @description This tool shows tables on database problems after you submit a wrong answer, so you don't need to read their unreadable JSON representation of tables. // @version 1.3 // @git f890188d315661aae24c2b05abfb6feac286c9fe // @namespace https://greatest.deepsurf.us/users/7949 // ==/UserScript== // @todo table sorting, diff functionality (function () { // dependancies inserted here // BEGIN INCLUDE sql_table.js /** * @file This module works with leetcode's json representable of tables. */ var sql_table = (function ( factory ) { var modulize = function ( factory, args ) { var callable = function () { return modulize( factory, arguments ); }; var obj = factory.apply( null, args ); for ( var prop in obj ) { if ( obj.hasOwnProperty( prop ) ) { callable[ prop ] = obj[ prop ]; } } return callable; }; return function () { return modulize( factory, arguments ); } })( function ( $, _ ) { /** @typedef {Object} Table @property {string} name The name of table @property {string[]} headers List of headers @property {Array[]} values Rows of table */ /** * Create table element from a leetcode json * @param {Table} obj Parsed json from "output" or "expected" field * @returns {jQuery} The table object */ var create_table_elem = function ( obj ) { /** * Return the HTML representation of value wrap in <td> * @param value * @return {jQuery} */ var repr_cell = function ( value ) { if ( _.isNull( value ) ) { return $( '<td>' ) .append( $( '<em>' ).text( 'NULL' ) ); } else if ( _.isString( value ) ) { return $( '<td>' ).text( JSON.stringify( value ) ); } else if ( _.isNumber( value ) ) { return $( '<td>' ) .text( value ) .css( 'text-align', 'right' ); } else { // unknown type return $( '<td>' ).text( value ); } }; /** * Wrap a list of text with tag * @param {string[]} arr * @param {string} tag * @returns {jQuery[]} Array of wrapping element */ var wrap_text = function ( arr, tag ) { return _( arr ).map( function ( txt ) { return $( tag ).text( txt ); } ); }; return $( '<table>' ) .append( $( '<caption>' ).text( obj.name ) ) .append( $( '<thead>' ) .append( $( '<tr>' ).append( wrap_text( obj.headers, '<th>' ) ) ) ) .append( $( '<tbody>' ) .append( _( obj.values ).map( function ( row ) { return $( '<tr>' ).append( _( row ).map( repr_cell ) ); } ) ) ); }; /** * Split the input json from leetcode to multiple table objects * @param {Object} obj Parsed json from "input" field * @param {Object.<string, string[]>} obj.headers Table name -> list of headers * @param {Object.<string, Array>} obj.rows Table name -> list of rows * @returns {Object.<string, Table>} Table name -> table object */ var split_input_table = function ( obj ) { var tables = {}; _( obj.headers ).each( function ( headers, table_name ) { var table = {}; table.name = table_name; table.headers = headers; table.values = obj.rows[ table_name ]; tables[ table_name ] = table; } ); return tables; }; return { create_table_elem: create_table_elem, split_input_table: split_input_table }; } ); // END INCLUDE sql_table.js // BEGIN INCLUDE bootstrap.js /** * @file Dependancy loader for user scripts. */ // ref: https://gist.github.com/cyranix/6180495 /** * @typedef {Object} JSModule * @property {string} url * @property {Function} has * @property {Function} get */ /** * Dependancy loader for user scripts. * @param {Function} main Main function of a user script, * call with loaded js modules * @param {Object} opts Required JS, CSS * @param {JSModule[]} [opts.modules=[]] Array of JS module specifiers * @param {string[]} [opts.css=[]] Array of URLs to CSS dependencies */ var bootstrap = function ( main, opts ) { /** * Load a js url and invoke callback * @param {string} url * @param {function} callback */ var load_js = function ( url, callback ) { var script = document.createElement( 'script' ); script.src = url; script.addEventListener( 'load', callback ); document.body.appendChild( script ); }; /** * Load a list of css urls * @param {string[]} url_list */ var load_css_multi = function ( url_list ) { while ( url_list.length > 0 ) { var head = document.getElementsByTagName( 'head' )[ 0 ]; var link = document.createElement( 'link' ); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = url_list.shift(); link.media = 'all'; head.appendChild( link ); } }; /** * Load a list of JS modules and invoke callback with a list of loaded module objects * @param {JSModule[]} mod_list * @param {Function} done * @param {Object[]} [loaded] */ var load_js_modules = function ( mod_list, done, loaded ) { loaded = loaded || []; if ( mod_list.length > 0 ) { var mod_specifier = mod_list.shift(); var existed = mod_specifier.has(); if ( existed ) { loaded.push( existed ); load_js_modules( mod_list, done, loaded ); } else { load_js( mod_specifier.url, function () { loaded.push( mod_specifier.get() ); load_js_modules( mod_list, done, loaded ); } ); } } else { done( loaded ); } }; var load_all = function () { var css_urls = opts.css || {}; var modules = opts.modules || []; load_css_multi( css_urls ); load_js_modules( modules, function ( mod_objs ) { // start main function main.apply( null, mod_objs ); } ); }; load_all(); }; // END INCLUDE bootstrap.js // BEGIN INCLUDE main.js /** * @file Main function of this user script */ // Arguments correspond to the dependency references. // @see {@link bootstrap} for further information. var main = function ( $, _, sql_table ) { // Is this a sql problem or sql submission var has_sql = $( '*[ng-switch-when=mysql]' ).length > 0 // sql problem || (window.pageData && window.pageData.getLangDisplay === 'mysql'); // sql submission if ( !has_sql ) { return; } // load sql_table module sql_table = sql_table( $, _ ); // get json from these elements var input_id = '#result_wa_testcase_input'; var output_id = '#result_wa_testcase_output'; var expected_id = '#result_wa_testcase_expected'; var last_exe_id = '#last_executed_testcase_output'; // styles for table var table_classes = [ 'pure-table', 'pure-table-bordered', 'pure-table-striped' ]; /** * Create table element from "input" field * @param {jQuery} el * @return {jQuery[]} Array of table element */ var get_input_tables = function ( el ) { // workaround: leetcode is replacing ',' with '\n' var json = JSON.parse( el.text().replace( /\n/g, ', ' ) ); return _( sql_table.split_input_table( json ) ).map( function ( table ) { return sql_table.create_table_elem( table ) .addClass( table_classes.join( ' ' ) ); } ); }; /** * Create table element from "output" or "expected" field * @param {jQuery} el * @return {jQuery} The table element */ var get_output_table = function ( el ) { var json = JSON.parse( el.text() ); return sql_table.create_table_elem( json ) .addClass( table_classes.join( ' ' ) ); }; /** * Render tables after "Wrong Answer" encountered. */ var show_table = function () { var table_ctn = $( '<div>' ) .append( '<hr>' ) .append( $( '<div>' ).text( 'Inputs:' ) ) .append( get_input_tables( $( input_id ) ) ) .append( '<hr>' ) .append( $( '<div class="pure-g">' ) .append( $( '<div class="pure-u-1-2">' ) .css( { color: 'red' } ) .append( $( '<div>' ).text( 'Output:' ) ) .append( get_output_table( $( output_id ) ) ) ) .append( $( '<div class="pure-u-1-2">' ) .css( { color: 'green' } ) .append( $( '<div>' ).text( 'Expected:' ) ) .append( get_output_table( $( expected_id ) ) ) ) ); var wa_output = $( '#wa_output' ); // remove prevous tables wa_output.children().first().nextAll().remove(); wa_output.append( table_ctn ); }; /** * Render tables after "Runtime Error" encountered. */ var show_le_table = function () { var table_ctn = $( '<div>' ) .append( '<hr>' ) .append( $( '<div>' ).text( 'Inputs:' ) ) .append( get_input_tables( $( last_exe_id ) ) ); var last_exe = $( '#last_executed_testcase_output_row' ); // remove prevous tables last_exe.children().first().nextAll().remove(); last_exe.append( table_ctn ); }; var create_show_table_btn = function () { var btn = $( '<button>' ) .text( 'Tablize!' ) .addClass( 'pure-button' ) .css( { 'margin-left': '16px' } ) .click( function () { show_table(); } ); $( '#more-details' ).after( btn ); }; /** * Invoke callback when element is visible. Using MutationObserver * @param {jQuery} elem * @param {function} func */ var setup_observer = function ( elem, func ) { var on_attr_changes = function () { if ( elem.is( ':visible' ) ) { func(); } }; // elem may be visible already on_attr_changes(); // observe style attribute changes var observer = new MutationObserver( on_attr_changes ); observer.observe( elem.get( 0 ), { attributes: true } ); }; /** * Invoke callback when element is visible. Using setInterval() * @param {jQuery} elem * @param {function} func */ var setup_poller = function ( elem, func ) { var is_showing = false; var check = function () { if ( elem.is( ':visible' ) ) { if ( !is_showing ) { func(); is_showing = true; } } else { is_showing = false; } }; window.setInterval( check, 500 ); }; var setup; if ( !window.MutationObserver ) { setup = setup_poller; } else { setup = setup_observer; } // show tables after wrong answer appeared setup( $( '#wa_output' ), show_table ); // show tables after a runtime errer setup( $( '#last_executed_testcase_output_row' ), show_le_table ); }; // END INCLUDE main.js bootstrap( main, { modules: [ { // jQuery url: '//cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js', has: function () { return window.jQuery; }, get: function () { return window.$.noConflict(); } }, { // underscore url: '//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js', has: function () { return undefined; }, get: function () { return window._.noConflict(); } }, { // sql_table has: function () { return sql_table; // direct reference } } ], css: [ // pure.css '//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css' ] } ); })();