Как в qt проверить скрипт javascript
Перейти к содержимому

Как в qt проверить скрипт javascript

  • автор:

Как в qt проверить скрипт javascript

Qt Script for Applications (QSA) — это инструментарий, обеспечивающий поддержку сценариев в приложениях, написанных на С++. QSA включает интерпретатор для языка Qt Script, который основан на ECMAScript (JavaScript). Программы, написанные с использованием Qt Script, имеют полный доступ к интерфейсу прикладного программирования (API) Qt и к любому API, который разработчики приложения захотят предоставить пользователям.

Введение

Инструментарий включает интегрированное средство разработки (IDE) Qt Script for Applications Designer (QSA Designer). QSA Designer похож на Qt Designer, но обладает дополнительной функциональностью, включая более развитый редактор кода и интегрированный отладчик.

QSA находится в состоянии бета-тестирования и, как ожидается, выйдет позже в этом (2002) году для платформ Windows, Unix/Linux и Mac OS X.

Что предоставляют сценарии?
  1. Независимо от функциональных возможностей и количества настроек приложения всегда бывают случаи, когда выбор пользователя оказывается в чем-то ограничен.
  2. Расширение функциональности и гибкости приложений, а также быстрое исправление ошибок могут обходиться очень дорого.
  1. Сценарии позволяют пользователям создавать собственные решения на базе функциональности, предоставляемой приложением.
  2. Сценарии позволяют отделам поддержки быстро и легко решать проблемы клиентов и исправлять ошибки без вмешательства в код приложений.
  3. Приложения с поддержкой сценариев более привлекательны для реселлеров. Они могут продавать готовые решения, основанные на приложениях и собственных сценариях.
  4. Приложения с поддержкой сценариев позволяют разработчикам сосредоточиться на создании базовых возможностей программы, а многочисленные функциональные вариации предоставить для реализации пользователям.

Поддержка сценариев — проверенное и широко используемое решение: от Microsoft Office VBA до Emacs Lisp. Некоторые клиенты Qt уже предлагают поддержку сценариев в своих приложениях на базе продуктов третьих фирм, поэтому потребность в поддержке сценариев для приложений Qt может быть удовлетворена Qt Script.

Добавление поддержки сценариев в приложение

    Собрать с библиотекой QSA.
    Для этого достаточно в файл .pro приложения добавить пару строк:

unix:LIBS += -lqsa win32:LIBS += $(QTDIR)\lib\qsa100.lib
void MyApp::addScript(const QString &funcName, const QPixmap &pixmap ) < QAction *a = new QAction( funcName, pixmap, funcName, 0, this, funcName.latin1() ); a->addTo( scriptsToolbar ); a->addTo( scriptsMenu ); connect( a, SIGNAL( activated() ), this, SLOT( runScript() ) ); >

В этом примере мы создаем объект QAction, добавляем его в меню и панель инструментов Qt Script, и связываем сигнал activated() с нашим слотом runScript().
Когда пользователь произведет выбор из меню или панели инструментов, сценарий будет выполнен с помощью функции call():

void MyApp::runScript() < QAction *action = (QAction*)sender(); QtApplicationScript::self()->call( action->text(), QValueList < QVariant >() ); >

Как мы увидели, добавление поддержки сценариев в приложение является простым делом. Чтобы получить доступ к механизму поддержки сценариев и программе QSA Designer, приложение должно быть собрано с библиотекой QSA. Как только библиотека QSA становится доступной, добавление объектов приложения в механизм поддержки сценариев, открытие проектов сценариев и предоставление пользователям возможности создания, редактирования, выполнения и отладки сценариев может быть достигнуто всего лишь с помощью нескольких строк кода.

QSA Designer

QSA Designer — это инструмент, который пользователи и разработчики используют для создания, редактирования, выполнения и отладки сценариев. QSA Designer включен в QSA-библиотеку и доступен всем приложениям. Кроме длинного названия QSA Designer включает средство создания GUI-интерфейса, аналогичное имеющемуся в Qt Designer, редактор кода Qt Script и интегрированный отладчик.

Интегрированная среда разработки использует те же самые подходы в создании GUI-интерфейса, что и Qt Designer. Пользователи могут приближенно размещать элементы интерфейса и выбором одного из типов компоновок в панели инструментов создавать масштабируемые диалоги. Также среда разработки позволяет легко связывать сигналы со слотами.

Если у пользователей не должно быть возможности создавать собственные диалоги, разработчики могут отключить возможности создания GUI в среде QSA Designer. В этом режиме пользователи могут создавать, редактировать, выполнять и отлаживать лишь не-GUI функции.

QSA Designer включает полностью интегрированный отладчик, который предлагает точки останова, пошаговое выполнение, отслеживание переменных и окно стека. Если в процессе отладки курсор мыши остановить над переменной, в окне всплывающей подсказки отобразится тип переменной и ее значение. Редактор кода имеет подсветку синтаксиса, авто-завершение, подсказку аргументов и сворачивание.

Внутри

Использование сценариев делает возможным интеграцию объектной модели приложения C++ с интерпретатором сценариев. Для QSA это означает, что большая часть Qt и, в особенности, объектная модель Qt должны быть доступны для Qt Script.

Предоставление доступа к откомпилированным функциям из сценариев называется ‘привязыванием’ (binding). Для осуществления привязывания применяются различные подходы, но наиболее распространенным является использование генератора кода, который производит синтаксический разбор объявлений классов C++, и на основе собранной информации для каждого класса создает обертку (wrapper), которая обычно является подклассом. В дальнейшем интерпретатор сценариев вызывает код обертки. Этот подход имеет два существенных недостатка: он сильно раздувает код, потому что подкласс обертки должен быть создан для каждого класса, и очень утомителен, потому что обертка должна быть создана для каждого класса, который разработчик захочет использовать в сценариях.

Подход, использованный в QSA, совершенно отличен, и основан на мета-объектной системе Qt. Мета-объектная система использует механизм сигналов и слотов, с которым знакомы все программисты Qt. Она также использует систему свойств Qt. Мета-объектная система может использоваться во время выполнения для создания и удаления связей сигнал-слот, для запросов, получения и изменения свойств, и для доступа к информации RTTI (Run Time Type Identification). Ни для одной из этих динамических возможностей не нужны подклассы оберток и не потребуется писать какой-либо другой код.

Небольшое количество кода, который предоставляет эти возможности, уже создано компилятором moc (Meta Object Compiler). В результате каждый класс и подкласс QObject, а также все их свойства, сигналы и слоты автоматически доступны для использования в сценариях. Не-QObject классы могут легко быть сделаны доступными для сценариев, если их обернуть в QObject. Этот подход работает даже для плагинов (plugins), поэтому классы или подклассы QObject, используемые в плагинах, будут доступны в сценариях.

Приведенная диаграмма показывает взаимосвязи между механизмом поддержки сценариев (QSA Library), приложением и сценариями приложения. Разработчики сценариев могут получить доступ непосредственно к объектам QObject, для которых был вызван метод addObject(), как будто эти объекты встроены в сам язык Qt Script. Объекты QObject могут быть объектами приложения или объектами, специально созданными разработчиками для программистов сценариев с целью предоставления им простого управления приложением. QSA Designer интегрирован с механизмом поддержки сценариев для обеспечения удобства создания, редактирования, выполнения и отладки сценариев.

Язык Qt Script

Qt Script основан на ECMAScript 4.0 (также известном, как JavaScript 2.0 или JScript.NET). Qt Script полностью объектно-ориентирован и использует объектную модель, подобную имеющейся в Qt. Он обладает возможностями современных языков, такими как использование высокоуровневых типов данных и управление исключениями, а также предлагает полный Qt API. Синтаксис Qt Script подобен C++ и Java, но менее сложен. Qt Script обеспечивает более богатые возможности, чем того требует ECMAScript; например, класс String обладает всей функциональностью QString. Такие расширения языка разрешены стандартом ECMAScript.

Ниже представленный код является примером реализации слота в Qt Script.

function buttonCalculate_clicked() < var divisor; switch ( comboCurrency.currentText ) < case "EUR": divisor = 1.13091; break; case "GBP": divisor = 0.700417; break; case "JPY": divisor = 131.446; break; >const spinOutCol = spinOutputColumn.value - 1; const spinCol = spinColumn.value - 1; for ( var i = spinStartRow.value - 1; i 

Переменные объявляются с помощью var, а не конкретным именем типа, потому что, как и большинство языков сценариев, Qt Script не является строго типизированным языком. Объекты comboCurrency, spinStartRow и другие ‘spin’-объекты являются элементами того же самого диалога, в котором размещена кнопка этого слота. Оператор with позволяет пользователям опускать подробные описания. Например, Application.sheet1.setText() и Application.sheet1.text() в представленном выше коде записаны как setText() и text(). Для доступа к глобальным объектам в слоте используется объект Application.

Основу языка Qt Script составляют арифметические и логические операторы, циклы for и while, операторы if, switch, и др., которые уже знакомы многочисленным пользователям языков JavaScript и JScript. Это обстоятельство наряду с гибкой функциональностью и простотой в использовании делает Qt Script идеальным языком сценариев для пользователей конечных приложений. Тем не менее, в некоторых отраслях промышленности и сегментах рынка пользователи уже столкнулись с другими языками сценариев, такими, как Python и Tcl. QSA-технология привязывания является нейтральной по отношению к языку, и поэтому в будущих версиях QSA другие языки будут получать поддержку по мере востребованности.

Подведение итогов

Приложения с поддержкой сценариев обеспечивают гибкость и выгоду для отделов поддержки и конечных пользователей, а также освобождают разработчиков от многочисленных функциональных вариаций. QSA предоставляет в распоряжение программистов сценариев все возможности Qt.

Библиотека QSA представляет собой готовое решение для включения его разработчиками в свои приложения. Она содержит интерпретатор языка сценариев и QSA Designer, мощную интегрированную среду разработки, предназначенную для создания, редактирования, выполнения и отладки сценариев конечными пользователями. QSA позволяет легко добавить в приложения поддержку сценариев. Если вы хотите узнать больше о QSA, пишите qsa@trolltech.com.

Проверка на наличие русских символов в QString

Проверка строки на наличие русских символов
Ребята помогите пожалуйста! Уже второй день мучаюсь, ситуация такая есть форма регистрации, на.

Проверка имени файла на наличие русских символов
Помоги,пожалуйста,осуществить проверку имени загружаемого файла на наличие русских символов и,если.

Проверка TextBox на наличие русских букв и цифр
Сори за ламерство, мне нужно, чтобы при нажатии на кнопку у меня проверялся текстбокс на наличие.

Синтаксический анализатор (проверка на наличие русских букв)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data;.

5042 / 4734 / 991
Регистрация: 11.10.2019
Сообщений: 12,418

Arbuzik345, попробуй два вот таких способа

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
QString str="12а3"; //1 for(const QChar& c:qAsConst(str))  } //2 if(str.contains(QRegularExpression("[А-Яа-я]+"))) { . }

Регистрация: 27.06.2020
Сообщений: 71

Алексей1153, 1 пропускает всё, а 2 чуть правильней, но пропускает те, в которых есть хотя-бы одна русская буква. Не то

5042 / 4734 / 991
Регистрация: 11.10.2019
Сообщений: 12,418

Arbuzik345, не понимаю, что значит — пропускает?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
QString str="12а3Бddfdfюg"; //1 for(const QChar& c:qAsConst(str))  if((c>=L'А' && cL'Я')  } //2 if(str.contains(QRegularExpression("[А-Яа-я]+"))) { qDebug()"contains"; } else { qDebug()"does not contain"; }

вывелись коды букв, можешь по таблице сравнить

Регистрация: 27.06.2020
Сообщений: 71

Алексей1153, возможно не до конца сформулировал вопрос и запутал вас. Мне нужно чтобы все символы в QString были русскими

5042 / 4734 / 991
Регистрация: 11.10.2019
Сообщений: 12,418

Лучший ответ

Сообщение было отмечено Arbuzik345 как решение

Решение

Arbuzik345, тогда так

1 2 3 4 5 6 7 8 9 10
QString str="абвАБВ"; if(str.contains(QRegularExpression("[^А-Яа-я]"))) { qDebug()"mixed"; } else { qDebug()"Rus only"; }

87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Проверка переменной на наличие только русских букв
Есть переменная var test = "привет"; можно ли как-то на JavaScript создать условие if которое.

Проверить строку на наличие русских символов
Здравствуйте. В строке могут быть русские символы, латинские символы, пробел, цифры, а так же.

Как проверить переменную на наличие русских символов ?
Как проверить переменную на наличие русских символов ?

Необходимо во веденной строке определить наличие русских и английских символов
Необходимо во веденной строке определить наличие русских и английских символов и,если есть.

Проверка русских символов в строке
Здравствуйте. Эта программка просит ввести строку,и если есть слово, заканчивающиеся на "к" +.

Проверка на наличие символов
Как написать функцию которая проверяет наличие символов (A-Z, a-z, 0-9) в строке и если есть любые.

Как распарсить html страницу на объекты в qt?

Нужно получить информацию, которая находится между html тегов (Например, div ). Исходный код страницы я получил, но какими инструментами QT, C++ или либами можно построить дерево из html, чтобы легко выдергивать содержимое тегов?

Отслеживать
8,900 11 11 золотых знаков 31 31 серебряный знак 55 55 бронзовых знаков
задан 30 мая 2016 в 10:55
Юрий Ватаман Юрий Ватаман
29 2 2 бронзовых знака
А вы каким классом получили страницу?
30 мая 2016 в 11:21
Если вам дан исчерпывающий ответ, отметьте его как верный (галка напротив выбранного ответа).
17 июн 2016 в 6:36

4 ответа 4

Сортировка: Сброс на вариант по умолчанию

Вы можете пойти другим путем – все действия, которые необходимо произвести со страницей выполняйте с помощью JavaScript, а в C++ обрабатывайте лишь результат. Поясню.

Представим, что у вас есть QWebEngineView

QWebEngineView *view; 

Вы можете назначить функцию обратного вызова для события загрузки страницы

connect(view, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool))); 

Вызвать загрузку целевой страницы

view->load(QUrl(requestUrl)); 

Когда загрузка будет выполнена, для упрощения работы с JavaScript, добавим JQuery. JQuery – строка полученная из ресурсного файла. После добавления JQuery, добавьте ваш JavaScript код и обработчик результата. Функция finishLoading может выглядеть следующим образом

void MyClass::finishLoading(bool) < view->page()->runJavaScript(JQuery::Instance()->Code()); view->page()->runJavaScript(YOUR_JS_CODE, invoke(this, &MyClass::onResultCallback)); > 

Где, YOUR_JS_CODE – QString с кодом обработки страницы. Например

const QString YOUR_JS_CODE = " \ function doSomething()< \ var results = $('.content'); \ if (results != 'undefined') \ return results.html(); \ return ''; \ >; doSomething();"; 

Обратите внимание, что необходимо вызвать добавленный код (последняя строка).

В завершении, вам необходимо обработать результат

void MyClass::onResultCallback(const QVariant& returnValue) < QString result = ""; bool isOk = false; result = returnValue.toString(&isOk); if (!isOk) < // Обработка ошибки return; >// Логика работы с результатом. > 

Для справки рекомендую посмотреть fancybrowser или основанный на нем querychecker.

Отслеживать
ответ дан 31 мая 2016 в 7:58
Nicolas Chabanovsky Nicolas Chabanovsky
51.2k 86 86 золотых знаков 266 266 серебряных знаков 505 505 бронзовых знаков

Если парсить через QWebKit , тогда используйте методы findAllElements и findFirstElement.

Нужно добавить в pro -файл в QT += webkit . Для Qt5 нужно также добавить QT += webkitwidgets

#include #include #include #include #include

В Qt5 инклуды будут такими:

#include #include 
QWebPage page; page.mainFrame()->setHtml("toHtml(); foreach (QWebElement el, page.mainFrame()->findAllElements("#content").toList())

В QWebKit для поиска используются css-селекторы — аналог xpath-запросов.

Отслеживать
ответ дан 30 мая 2016 в 13:55
76.7k 6 6 золотых знаков 54 54 серебряных знака 121 121 бронзовый знак

Спасибо за ответ. Но беда в том что в последних версиях Qt нет возможности использовать Qwebkit. Вместо него как я понимаю QtWebengine. Вот как добиться этого с помощью него.

30 мая 2016 в 15:49

Хотелось бы узнать за что мне минус поставили, за работающий пример? 🙂 @Duracell, минус вам не я, если что, поставил 🙂

30 мая 2016 в 18:43
@ЮрийВатаман, обновил ответ. Компилировал и запускал на Qt 5.4.2
30 мая 2016 в 18:57

@gil9red — извиняюсь, исправил, думал нахожусь в другой теме, этот минус был другому человеку, за другой ответ.

31 мая 2016 в 7:14
@gil9red , автор, вероятно, имеет в виду версию Qt 5.6, где действительно QtWebKit не подключить.
– user177227
31 мая 2016 в 7:16

Могу предложить парсинг через Qt XML , я не знаю будет ли он работать в HTML, по идее должен, далее выдержка из Qt Assistant , из описания класса QDomDocument . Если нужны какие-то конкретные вопросы, то пишите в комментарии. Если хотите парсить html любой вложенности, то нужно использовать рекурсивные вызовы. И не забудьте в *.pro добавить QT += xml .

QDomDocument doc("mydocument"); QFile file("mydocument.xml"); if (!file.open(QIODevice::ReadOnly)) return; if (!doc.setContent(&file)) < file.close(); return; >file.close(); // print out the element names of all elements that are direct children // of the outermost element. QDomElement docElem = doc.documentElement(); QDomNode n = docElem.firstChild(); while(!n.isNull()) < QDomElement e = n.toElement(); // try to convert the node to an element. if(!e.isNull()) < cout n = n.nextSibling(); > 

Гибридные приложения в Qt на примере использования D3.js

D3 — мощная JavaScript библиотека для визуализации данных. На мой взгляд — просто рай для web-разработчика, казалось бы недоступный для Qt-программиста. Но гибкость фреймворка Qt позволяет интегрировать web-frontend в толстый клиент с помощью механизма Qt Web Bridge. Такие приложения получили наименование гибридные (Qt Hybrid Apps).

Для JavaScript-программистов хорошая новость заключается в том, что их решения можно легко интегрировать в Desktop приложения, что потенциально может увеличить целевую аудиторию пользователей разрабатываемых библиотек (во всяком случае это верно для мира Qt приложений).

На скриншоте ниже изображен виджет Dependency Wheel (Круг Зависимостей), отрисовка которого осуществляется с помощью D3.js а управление данными и отображением — с помощью Qt. При нахождении указателя над соответствующей дугой её взаимосвязи «подсвечиваются», а остальные становятся полупрозначными. Данный виджет можно использовать для визуализации различного рода зависимостей (например библиотек).

В отличии от оригинального JS решения диаграмма динамически изменяет размер под размер виджета, а данные устанавливаются на стороне Qt, а не с помощью загрузки JSON-файла.

Статья больше ориентирована на Qt-программистов, но также может быть интересна и JS программистам.

Идея гибридных приложений
  • дополнительные расходы по внедрению и сопровождению клиентских частей системы;
  • написание уникального интерфейса пользователя порой является нетривиальной задачей;
  • невозможность повторного использовать API существующих веб-приложений.
  • развертывание выполняется как в веб приложениях;
  • сложные интерфейсы создаются с использованием web-технологий (HTML, CSS, SVG, Canvas);
  • повторно используется API существующих веб-приложений.
  • Qt-приложение выступает в роли браузера;
  • взаимодействие с пользователем и логика приложения программируется в JavaScript;
  • дополнительная функциональность реализуется на С++ в Qt-части приложения.

В примере, рассматриваемом в статье, будет использована только часть подхода гибридных приложений: отображение компонента за счет JavaScript. При этом все необходимые JS файлы будут расположены в ресурсах, как в классическом StandAlone приложении (автономном и не требующем для работы подключения к интранет/интернет сети).

Структура проекта

Общая структура файлов проекта изображена на рисунке:

  • d3viewer.h и d3viewer.cpp — определение и реализация базового класса-вьювера D3Viewer, наследованного от QWidget и инкапсулирующего взаимодействие с QWebView.
  • d3webpage.h и d3webpage.cpp — определение и реализация D3WebPage — наследника QWebPage (для поддержки вывода сообщений об ошибках и отладочной информации в QWebPage::javaScriptConsoleMessage).
  • dependencywheelwidget.h и dependencywheelwidget.cpp — определение и реализация базового класса-вьювера, наследованного от QWidget и инкапсулирующего взаимодействие с QWebView.
Диаграмма классов

Для того, чтобы сократить объем статьи средствами VisualParadigm была создана простая диаграмма: в ней опущены атрибуты и методы классов, которые не имеют прямого отношения к описываемой технологии. Детали реализации можно узнать в исходниках, ссылка на которые находится в конце статьи.

Взаимодействие Qt JS

В гибридных приложениях в JavaScript внедряется специальный объект, вызов методов которого обрабатывается на стороне Qt:

void D3Viewer::addContextObject(const QString &name, QObject *object) < frame()->addToJavaScriptWindowObject( name, object ); //frame() - QWebFrame > 

Этот метод вызывается в производных от D3Viewer классах в конструкторе перед загрузкой страницы:

addContextObject("api", this); 

    Посредством обращения к свойствам объекта.
    для этого необходимо определить свойство в объекте, который является контекстным объектом в JS («api»):

public: Q_PROPERTY(float padding READ padding WRITE setPadding) public slots: float padding(); //getter void setPadding(const float padding); //setter 

После этого можно обращаться к данным свойствам из JS:

 var chart = d3.chart.dependencyWheel() .width(api.width) .height(api.height) .margin(api.margin) .padding(api.padding); 
api.update.connect(redraw); 
 g.append("svg:path") .style("fill", fill) .style("stroke", fill) .attr("d", arc) .on("mouseover", fade(0.1)) .on("mouseout", fade(1)) .on('click', function (d) < api.itemClicked(packageNames[d.index]) >); //здесь подключается обработчик 
Q_INVOKABLE void thisMethodIsInvokableInJavaScript(); 
void D3Viewer::evaluateScript(const QString &script) < frame()->evaluateJavaScript(script); > 
Отладка JavaScript в гибридном приложении

Для отладки JS приложения (как и обзора DOM, просмотра сетевой активности, загружаемых ресурсов и т.д.) в конструкторе D3Viewer необходимо установить следующее свойство:

#ifdef QT_DEBUG //в этом случае контекстное меню будет доступно только в отладочной сборке page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); #endif 

Тогда во время выполнения в контекстном меню (щелчок правой кнопки мыши по QWebView) будет доступно пункт контекстного меню «Проверить» (Inspect).

Выбрав который отображается окно Web-inspector-a.

В данном окне на вкладке Scripts можно включить отладку.

Установка breakpoint-а осуществляется кликом по соответствующему номеру строки слева.
P.S. В Qt 4.8.6 мне так и не получилось перехватить breakpoint. В 5.3.0 все работает штатно.

Недостатки
  • Дополнительные накладные расходы (в первую очередь памяти).
    Помимо того, что QWebView «тянет» за собой webkit, создавая новый «гибридный» виджет мы заново создаем достаточно тяжеловесный объект QWebView. Это не так актуально, если весь UI грузится в одном QWebView (как предлагается в оригинальной идее гибридных приложений).
  • Риск невозможности обратного повторного использования в web после модификации JS. Под нужды Qt можно так модифицировать JavaScript код, что он станет непригоден в web-приложении. Поэтому все обращения к Qt-объекту api желательно изолировать в одном месте — например в секции script html файла, который в данном случае будет разный для web и Qt приложения а JS код в подключаемых файлах будет единым.
  • Баги WebKit-а в Qt 4.8.6
    В D3 активно используются древовидные структуры, описание которых находится в JSON файлах. На стороне Qt формируется такой же JSON объект посредством комбинации QVariantMap/QVariantList приведенных в итоге к QVariant. Несмотря на то, что структура, таких объектов идентична, в Qt 4.8.6 все же есть отличия, так как напрямую такой объект не воспринимается и приходится повторно «пересоздать» JSON объект в памяти на стороне JS. В Qt 5.3.0 такой костыль можно не использовать — все работает напрямую.

function recreateJsonObject(obj) < var jsonObj = <>; for(key in obj) < jsonObj[key] = obj[key]; var dependencies = []; for (var i = 0 ; i < obj[key].length ; i++ ) < dependencies.push(obj[key][i]); >jsonObj[key] = dependencies; > return jsonObj; > 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *