ProShell v2.0
Dashboard
Server Info
Server: 158.106.128.192
PHP: 8.2.33
home
planet5
public_html
bansibaba.com
wp-includes
2026-09-16 22:42:19
Editing: atd.core.js
Cancel
Save Changes
/* * atd.core.js - A building block to create a front-end for AtD * Author : Raphael Mudge, Automattic * License : LGPL * Project : http://www.afterthedeadline.com/developers.slp * Contact : raffi@automattic.com */ /* jshint sub: true, devel: true, onevar: false, smarttabs: true, loopfunc: true */ /* exported EXPORTED_SYMBOLS, atd_sprintf */ /* EXPORTED_SYMBOLS is set so this file can be a JavaScript Module */ var EXPORTED_SYMBOLS = ['AtDCore']; function AtDCore() { /* these are the categories of errors AtD should ignore */ this.ignore_types = ['Bias Language', 'Cliches', 'Complex Expression', 'Diacritical Marks', 'Double Negatives', 'Hidden Verbs', 'Jargon Language', 'Passive voice', 'Phrases to Avoid', 'Redundant Expression']; /* these are the phrases AtD should ignore */ this.ignore_strings = {}; /* Localized strings */ // Back-compat, not used this.i18n = {}; } /* * Internationalization Functions */ AtDCore.prototype.getLang = function( key, defaultk ) { return ( window.AtD_l10n_r0ar && window.AtD_l10n_r0ar[key] ) || defaultk; }; AtDCore.prototype.addI18n = function( obj ) { // Back-compat window.AtD_l10n_r0ar = obj; }; /* * Setters */ AtDCore.prototype.setIgnoreStrings = function(string) { var parent = this; this.map(string.split(/,\s*/g), function(string) { parent.ignore_strings[string] = 1; }); }; AtDCore.prototype.showTypes = function(string) { var show_types = string.split(/,\s*/g); var types = {}; /* set some default types that we want to make optional */ /* grammar checker options */ types['Double Negatives'] = 1; types['Hidden Verbs'] = 1; types['Passive voice'] = 1; types['Bias Language'] = 1; /* style checker options */ types['Cliches'] = 1; types['Complex Expression'] = 1; types['Diacritical Marks'] = 1; types['Jargon Language'] = 1; types['Phrases to Avoid'] = 1; types['Redundant Expression'] = 1; var ignore_types = []; this.map(show_types, function(string) { types[string] = undefined; }); this.map(this.ignore_types, function(string) { if (types[string] !== undefined) { ignore_types.push(string); } }); this.ignore_types = ignore_types; }; /* * Error Parsing Code */ AtDCore.prototype.makeError = function(error_s, tokens, type, seps/*, pre*/) { var struct = {}; struct.type = type; struct.string = error_s; struct.tokens = tokens; if (new RegExp('\\b' + error_s + '\\b').test(error_s)) { struct.regexp = new RegExp('(?!'+error_s+'<)\\b' + error_s.replace(/\s+/g, seps) + '\\b'); } else if (new RegExp(error_s + '\\b').test(error_s)) { struct.regexp = new RegExp('(?!'+error_s+'<)' + error_s.replace(/\s+/g, seps) + '\\b'); } else if (new RegExp('\\b' + error_s).test(error_s)) { struct.regexp = new RegExp('(?!'+error_s+'<)\\b' + error_s.replace(/\s+/g, seps)); } else { struct.regexp = new RegExp('(?!'+error_s+'<)' + error_s.replace(/\s+/g, seps)); } struct.used = false; /* flag whether we've used this rule or not */ return struct; }; AtDCore.prototype.addToErrorStructure = function(errors, list, type, seps) { var parent = this; this.map(list, function(error) { var tokens = error['word'].split(/\s+/); var pre = error['pre']; var first = tokens[0]; if (errors['__' + first] === undefined) { errors['__' + first] = {}; errors['__' + first].pretoks = {}; errors['__' + first].defaults = []; } if (pre === '') { errors['__' + first].defaults.push(parent.makeError(error['word'], tokens, type, seps, pre)); } else { if (errors['__' + first].pretoks['__' + pre] === undefined) { errors['__' + first].pretoks['__' + pre] = []; } errors['__' + first].pretoks['__' + pre].push(parent.makeError(error['word'], tokens, type, seps, pre)); } }); }; AtDCore.prototype.buildErrorStructure = function(spellingList, enrichmentList, grammarList) { var seps = this._getSeparators(); var errors = {}; this.addToErrorStructure(errors, spellingList, 'hiddenSpellError', seps); this.addToErrorStructure(errors, grammarList, 'hiddenGrammarError', seps); this.addToErrorStructure(errors, enrichmentList, 'hiddenSuggestion', seps); return errors; }; AtDCore.prototype._getSeparators = function() { var re = '', i; var str = '"s!#$%&()*+,./:;<=>?@[\\]^_{|}'; // Build word separator regexp for (i=0; i<str.length; i++) { re += '\\' + str.charAt(i); } return '(?:(?:[\xa0' + re + '])|(?:\\-\\-))+'; }; AtDCore.prototype.processXML = function(responseXML) { /* types of errors to ignore */ var types = {}; this.map(this.ignore_types, function(type) { types[type] = 1; }); /* save suggestions in the editor object */ this.suggestions = []; /* process through the errors */ var errors = responseXML.getElementsByTagName('error'); /* words to mark */ var grammarErrors = []; var spellingErrors = []; var enrichment = []; for (var i = 0; i < errors.length; i++) { if (errors[i].getElementsByTagName('string').item(0).firstChild !== null) { var errorString = errors[i].getElementsByTagName('string').item(0).firstChild.data; var errorType = errors[i].getElementsByTagName('type').item(0).firstChild.data; var errorDescription = errors[i].getElementsByTagName('description').item(0).firstChild.data; var errorContext; if (errors[i].getElementsByTagName('precontext').item(0).firstChild !== null) { errorContext = errors[i].getElementsByTagName('precontext').item(0).firstChild.data; } else { errorContext = ''; } /* create a hashtable with information about the error in the editor object, we will use this later to populate a popup menu with information and suggestions about the error */ if (this.ignore_strings[errorString] === undefined) { var suggestion = {}; suggestion['description'] = errorDescription; suggestion['suggestions'] = []; /* used to find suggestions when a highlighted error is clicked on */ suggestion['matcher'] = new RegExp('^' + errorString.replace(/\s+/, this._getSeparators()) + '$'); suggestion['context'] = errorContext; suggestion['string'] = errorString; suggestion['type'] = errorType; this.suggestions.push(suggestion); if (errors[i].getElementsByTagName('suggestions').item(0) !== null) { var suggestions = errors[i].getElementsByTagName('suggestions').item(0).getElementsByTagName('option'); for (var j = 0; j < suggestions.length; j++) { suggestion['suggestions'].push(suggestions[j].firstChild.data); } } /* setup the more info url */ if (errors[i].getElementsByTagName('url').item(0) !== null) { var errorUrl = errors[i].getElementsByTagName('url').item(0).firstChild.data; suggestion['moreinfo'] = errorUrl + '&theme=tinymce'; } if (types[errorDescription] === undefined) { if (errorType === 'suggestion') { enrichment.push({ word: errorString, pre: errorContext }); } if (errorType === 'grammar') { grammarErrors.push({ word: errorString, pre: errorContext }); } } if (errorType === 'spelling' || errorDescription === 'Homophone') { spellingErrors.push({ word: errorString, pre: errorContext }); } if (errorDescription === 'Cliches') { suggestion['description'] = 'Clichés'; /* done here for backwards compatability with current user settings */ } if (errorDescription === 'Spelling') { suggestion['description'] = this.getLang('menu_title_spelling', 'Spelling'); } if (errorDescription === 'Repeated Word') { suggestion['description'] = this.getLang('menu_title_repeated_word', 'Repeated Word'); } if (errorDescription === 'Did you mean...') { suggestion['description'] = this.getLang('menu_title_confused_word', 'Did you mean...'); } } // end if ignore[errorString] == undefined } // end if } // end for loop var errorStruct; var ecount = spellingErrors.length + grammarErrors.length + enrichment.length; if (ecount > 0) { errorStruct = this.buildErrorStructure(spellingErrors, enrichment, grammarErrors); } else { errorStruct = undefined; } /* save some state in this object, for retrieving suggestions later */ return { errors: errorStruct, count: ecount, suggestions: this.suggestions }; }; AtDCore.prototype.findSuggestion = function(element) { var text = element.innerHTML; var context = ( this.getAttrib(element, 'pre') + '' ).replace(/[\\,!\\?\\."\s]/g, ''); if (this.getAttrib(element, 'pre') === undefined) { alert(element.innerHTML); } var errorDescription; var len = this.suggestions.length; for (var i = 0; i < len; i++) { if ((context === '' || context === this.suggestions[i]['context']) && this.suggestions[i]['matcher'].test(text)) { errorDescription = this.suggestions[i]; break; } } return errorDescription; }; /* * TokenIterator class */ function TokenIterator(tokens) { this.tokens = tokens; this.index = 0; this.count = 0; this.last = 0; } TokenIterator.prototype.next = function() { var current = this.tokens[this.index]; this.count = this.last; this.last += current.length + 1; this.index++; /* strip single quotes from token, AtD does this when presenting errors */ if (current !== '') { if (current[0] === '\'') { current = current.substring(1, current.length); } if (current[current.length - 1] === '\'') { current = current.substring(0, current.length - 1); } } return current; }; TokenIterator.prototype.hasNext = function() { return this.index < this.tokens.length; }; TokenIterator.prototype.hasNextN = function(n) { return (this.index + n) < this.tokens.length; }; TokenIterator.prototype.skip = function(m, n) { this.index += m; this.last += n; if (this.index < this.tokens.length) { this.count = this.last - this.tokens[this.index].length; } }; TokenIterator.prototype.getCount = function() { return this.count; }; TokenIterator.prototype.peek = function(n) { var peepers = []; var end = this.index + n; for (var x = this.index; x < end; x++) { peepers.push(this.tokens[x]); } return peepers; }; /* * code to manage highlighting of errors */ AtDCore.prototype.markMyWords = function(container_nodes, errors) { var seps = new RegExp(this._getSeparators()), nl = [], ecount = 0, /* track number of highlighted errors */ parent = this, bogus = this._isTinyMCE ? ' data-mce-bogus="1"' : '', emptySpan = '<span class="mceItemHidden"' + bogus + '> </span>', textOnlyMode; /** * Split a text node into an ordered list of siblings: * - text node to the left of the match * - the element replacing the match * - text node to the right of the match * * We have to leave the text to the left and right of the match alone * in order to prevent XSS * * @return array */ function splitTextNode( textnode, regexp, replacement ) { var text = textnode.nodeValue, index = text.search( regexp ), match = text.match( regexp ), captured = [], cursor; if ( index < 0 || ! match.length ) { return [ textnode ]; } if ( index > 0 ) { // capture left text node captured.push( document.createTextNode( text.substr( 0, index ) ) ); } // capture the replacement of the matched string captured.push( parent.create( match[0].replace( regexp, replacement ) ) ); cursor = index + match[0].length; if ( cursor < text.length ) { // capture right text node captured.push( document.createTextNode( text.substr( cursor ) ) ); } return captured; } function _isInPre( node ) { if ( node ) { while ( node.parentNode ) { if ( node.nodeName === 'PRE' ) { return true; } node = node.parentNode; } } return false; } /* Collect all text nodes */ /* Our goal--ignore nodes that are already wrapped */ this._walk( container_nodes, function( n ) { if ( n.nodeType === 3 && ! parent.isMarkedNode( n ) && ! _isInPre( n ) ) { nl.push( n ); } }); /* walk through the relevant nodes */ var iterator; this.map( nl, function( n ) { var v; if ( n.nodeType === 3 ) { v = n.nodeValue; /* we don't want to mangle the HTML so use the actual encoded string */ var tokens = n.nodeValue.split( seps ); /* split on the unencoded string so we get access to quotes as " */ var previous = ''; var doReplaces = []; iterator = new TokenIterator(tokens); while ( iterator.hasNext() ) { var token = iterator.next(); var current = errors['__' + token]; var defaults; if ( current !== undefined && current.pretoks !== undefined ) { defaults = current.defaults; current = current.pretoks['__' + previous]; var done = false; var prev, curr; prev = v.substr(0, iterator.getCount()); curr = v.substr(prev.length, v.length); var checkErrors = function( error ) { if ( error !== undefined && ! error.used && foundStrings[ '__' + error.string ] === undefined && error.regexp.test( curr ) ) { foundStrings[ '__' + error.string ] = 1; doReplaces.push([ error.regexp, '<span class="'+error.type+'" pre="'+previous+'"' + bogus + '>$&</span>' ]); error.used = true; done = true; } }; // jshint ignore:line var foundStrings = {}; if (current !== undefined) { previous = previous + ' '; parent.map(current, checkErrors); } if (!done) { previous = ''; parent.map(defaults, checkErrors); } } previous = token; } // end while /* do the actual replacements on this span */ if ( doReplaces.length > 0 ) { var newNode = n; for ( var x = 0; x < doReplaces.length; x++ ) { var regexp = doReplaces[x][0], result = doReplaces[x][1]; /* it's assumed that this function is only being called on text nodes (nodeType == 3), the iterating is necessary because eventually the whole thing gets wrapped in an mceItemHidden span and from there it's necessary to handle each node individually. */ var bringTheHurt = function( node ) { var span, splitNodes; if ( node.nodeType === 3 ) { ecount++; /* sometimes IE likes to ignore the space between two spans, solution is to insert a placeholder span with a non-breaking space. The markup removal code substitutes this span for a space later */ if ( parent.isIE() && node.nodeValue.length > 0 && node.nodeValue.substr(0, 1) === ' ' ) { return parent.create( emptySpan + node.nodeValue.substr( 1, node.nodeValue.length - 1 ).replace( regexp, result ), false ); } else { if ( textOnlyMode ) { return parent.create( node.nodeValue.replace( regexp, result ), false ); } span = parent.create( '<span />' ); if ( typeof textOnlyMode === 'undefined' ) { // cache this to avoid adding / removing nodes unnecessarily textOnlyMode = typeof span.appendChild !== 'function'; if ( textOnlyMode ) { parent.remove( span ); return parent.create( node.nodeValue.replace( regexp, result ), false ); } } // "Visual" mode splitNodes = splitTextNode( node, regexp, result ); for ( var i = 0; i < splitNodes.length; i++ ) { span.appendChild( splitNodes[i] ); } node = span; return node; } } else { var contents = parent.contents(node); for ( var y = 0; y < contents.length; y++ ) { if ( contents[y].nodeType === 3 && regexp.test( contents[y].nodeValue ) ) { var nnode; if ( parent.isIE() && contents[y].nodeValue.length > 0 && contents[y].nodeValue.substr(0, 1) === ' ') { nnode = parent.create( emptySpan + contents[y].nodeValue.substr( 1, contents[y].nodeValue.length - 1 ).replace( regexp, result ), true ); } else { nnode = parent.create( contents[y].nodeValue.replace( regexp, result ), true ); } parent.replaceWith( contents[y], nnode ); parent.removeParent( nnode ); ecount++; return node; /* we did a replacement so we can call it quits, errors only get used once */ } } return node; } }; // jshint ignore:line newNode = bringTheHurt(newNode); } parent.replaceWith(n, newNode); } } }); return ecount; }; AtDCore.prototype._walk = function(elements, f) { var i; for (i = 0; i < elements.length; i++) { f.call(f, elements[i]); this._walk(this.contents(elements[i]), f); } }; AtDCore.prototype.removeWords = function(node, w) { var count = 0; var parent = this; this.map(this.findSpans(node).reverse(), function(n) { if (n && (parent.isMarkedNode(n) || parent.hasClass(n, 'mceItemHidden') || parent.isEmptySpan(n)) ) { if (n.innerHTML === ' ') { var nnode = document.createTextNode(' '); /* hax0r */ parent.replaceWith(n, nnode); } else if (!w || n.innerHTML === w) { parent.removeParent(n); count++; } } }); return count; }; AtDCore.prototype.isEmptySpan = function(node) { return (this.getAttrib(node, 'class') === '' && this.getAttrib(node, 'style') === '' && this.getAttrib(node, 'id') === '' && !this.hasClass(node, 'Apple-style-span') && this.getAttrib(node, 'mce_name') === ''); }; AtDCore.prototype.isMarkedNode = function(node) { return (this.hasClass(node, 'hiddenGrammarError') || this.hasClass(node, 'hiddenSpellError') || this.hasClass(node, 'hiddenSuggestion')); }; /* * Context Menu Helpers */ AtDCore.prototype.applySuggestion = function(element, suggestion) { if (suggestion === '(omit)') { this.remove(element); } else { var node = this.create(suggestion); this.replaceWith(element, node); this.removeParent(node); } }; /* * Check for an error */ AtDCore.prototype.hasErrorMessage = function(xmlr) { return (xmlr !== undefined && xmlr.getElementsByTagName('message').item(0) !== null); }; AtDCore.prototype.getErrorMessage = function(xmlr) { return xmlr.getElementsByTagName('message').item(0); }; /* this should always be an error, alas... not practical */ AtDCore.prototype.isIE = function() { return navigator.appName === 'Microsoft Internet Explorer'; }; // TODO: this doesn't seem used anywhere in AtD, moved here from install_atd_l10n.js for eventual back-compat /* a quick poor man's sprintf */ function atd_sprintf(format, values) { var result = format; for (var x = 0; x < values.length; x++) { result = result.replace(new RegExp('%' + (x + 1) + '\\$', 'g'), values[x]); } return result; }
Upload Files
Cancel
Upload
Create New
Cancel
Create
Change Permissions
Cancel
Save
Change Date
Cancel
Save
Rename Item
Cancel
Save
Confirm Delete
Are you sure you want to delete the selected items?
Cancel
Delete