/
githubmirror
/
brackets
Обзор
Документация
Войти
/
githubmirror
/
brackets
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/LiveDevelopment/Agents/DOMHelpers.js
267 строк
9 KB
ficristo
Move most inline jslint directives to config files
12 авг 2016, 10:22
12 авг 2016, 10:22
074382a
Код
Авторство
О чём код?
/* * Copyright (c) 2012 - present Adobe Systems Incorporated. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ /*jslint regexp: true */ /** * DOMHelpers is a collection of functions used by the DOMAgent exports `eachNode(src, callback)` */ define(function DOMHelpersModule(require, exports, module) { "use strict"; /** Test if the given character is a quote character * {char} source character * {char} escape (previous) character * {char} quote character */ function _isQuote(c, escape, quote) { if (escape === "\\") { return false; } if (quote !== undefined) { return c === quote; } return c === "\"" || c === "'"; } /** Remove quotes from the string and adjust escaped quotes * @param {string} source string */ function _removeQuotes(src) { if (_isQuote(src[0]) && src[src.length - 1] === src[0]) { var q = src[0]; src = src.substr(1, src.length - 2); src = src.replace("\\" + q, q); } return src; } /** Find the next match using several constraints * @param {string} source string * @param {string} or [{regex}, {length}] the match definition * @param {integer} ignore characters before this offset * @param {boolean} watch for quotes * @param [{string},{string}] watch for comments */ function _find(src, match, skip, quotes, comments) { if (typeof match === "string") { match = [match, match.length]; } if (skip === undefined) { skip = 0; } var i, activeQuote, isComment = false; for (i = skip; i < src.length; i++) { if (quotes && _isQuote(src[i], src[i - 1], activeQuote)) { // starting quote activeQuote = activeQuote ? undefined : src[i]; } else if (!activeQuote) { if (comments && !isComment && src.substr(i, comments[0].length) === comments[0]) { // opening comment isComment = true; i += comments[0].length - 1; } else if (isComment) { // we are commented if (src.substr(i, comments[1].length) === comments[1]) { isComment = false; i += comments[1].length - 1; } } else if (src.substr(i, match[1]).search(match[0]) === 0) { // match return i; } } } return -1; } /** Callback iterator using `_find` */ function _findEach(src, match, quotes, comments, callback) { var from = 0; var to; while (from < src.length) { to = _find(src, match, from, quotes, comments); if (to < 0) { to = src.length; } callback(src.substr(from, to - from)); from = to + 1; } } /** Find the next tag * @param {string} source string * @param {integer} ignore characters before this offset */ function _findTag(src, skip) { var from, to, inc; from = _find(src, [/<[a-z!\/]/i, 2], skip); if (from < 0) { return null; } if (src.substr(from, 4) === "<!--") { // html comments to = _find(src, "-->", from + 4); inc = 3; } else if (src.substr(from, 7).toLowerCase() === "<script") { // script tag to = _find(src.toLowerCase(), "</script>", from + 7); inc = 9; } else if (src.substr(from, 6).toLowerCase() === "<style") { // style tag to = _find(src.toLowerCase(), "</style>", from + 6); inc = 8; } else { to = _find(src, ">", from + 1, true); inc = 1; } if (to < 0) { return null; } return {from: from, length: to + inc - from}; } /** Extract tag attributes from the given source of a single tag * @param {string} source content */ function _extractAttributes(content) { // remove the node name and the closing bracket and optional slash content = content.replace(/^<\S+\s*/, ""); content = content.replace(/\s*\/?>$/, ""); if (content.length === 0) { return; } // go through the items and identify key value pairs split by = var index, key, value; var attributes = {}; _findEach(content, [/\s/, 1], true, undefined, function each(item) { index = item.search("="); if (index < 0) { return; } // get the key key = item.substr(0, index).trim(); if (key.length === 0) { return; } // get the value value = item.substr(index + 1).trim(); value = _removeQuotes(value); attributes[key] = value; }); return attributes; } /** Extract the node payload * @param {string} source content */ function extractPayload(content) { var payload = {}; if (content[0] !== "<") { // text payload.nodeType = 3; payload.nodeValue = content; } else if (content.substr(0, 4) === "<!--") { // comment payload.nodeType = 8; payload.nodeValue = content.substr(4, content.length - 7); } else if (content[1] === "!") { // doctype payload.nodeType = 10; } else { // regular element payload.nodeType = 1; payload.nodeName = /^<([^>\s]+)/.exec(content)[1].toUpperCase(); payload.attributes = _extractAttributes(content); // closing node (/ at the beginning) if (payload.nodeName[0] === "/") { payload.nodeName = payload.nodeName.substr(1); payload.closing = true; } // closed node (/ at the end) if (content[content.length - 2] === "/") { payload.closed = true; } // Special handling for script/style tag since we've already collected // everything up to the end tag. if (payload.nodeName === "SCRIPT" || payload.nodeName === "STYLE") { payload.closed = true; } } return payload; } /** Split the source string into payloads representing individual nodes * @param {string} source * @param {function(payload)} callback */ // split a string into individual node contents function eachNode(src, callback) { var index = 0; var text, range, length, payload; while (index < src.length) { // find the next tag range = _findTag(src, index); if (!range) { range = { from: src.length, length: 0 }; } // add the text before the tag length = range.from - index; if (length > 0) { text = src.substr(index, length); if (/\S/.test(text)) { payload = extractPayload(text); payload.sourceOffset = index; payload.sourceLength = length; callback(payload); } } // add the tag if (range.length > 0) { payload = extractPayload(src.substr(range.from, range.length)); payload.sourceOffset = range.from; payload.sourceLength = range.length; callback(payload); } // advance index = range.from + range.length; } } // Export public functions exports.extractPayload = extractPayload; exports.eachNode = eachNode; });