Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CodeFest 2019. Валерия Зелёная (HTML Academy) —...

CodeFest
April 06, 2019

CodeFest 2019. Валерия Зелёная (HTML Academy) — Как технологии помогают учить людей

Интерактивные онлайн-курсы дают возможность учиться разработке в любое время и в любом месте. Но как пользователю узнать, что его решение правильное, и он действительно разобрался, как работают события и замыкания?

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

CodeFest

April 06, 2019
Tweet

More Decks by CodeFest

Other Decks in Technology

Transcript

  1. 13

  2. Запуск кода – Песочница — айфрейм, скрытый на странице –

    Нодовский пакет vm создаёт айфреймы 13
  3. Запуск кода – Песочница — айфрейм, скрытый на странице –

    Нодовский пакет vm создаёт айфреймы – Контекст — способ vm настроить глобальный объект window для айфрейма: – Переопределение дефолтных методов (например, console.log ) – Определение кастомных методов (keks.ask, keks.score) 14
  4. Запуск кода – Песочница — айфрейм, скрытый на странице –

    Нодовский пакет vm создаёт айфреймы – Контекст — способ vm настроить глобальный объект window для айфрейма: – Переопределение дефолтных методов (например, console.log ) – Определение кастомных методов (keks.ask, keks.score) – Ловим вызов методов и выводим в нашу консоль 15
  5. Создание песочницы 16 !// Определяем наши методы
 const sandbox =

    vm.createContext({
 console: {
 log: (message) => {
 myConsole.appendChild(message);
 }
 }
 });
 !// Запускаем код юзера в контексте песочницы
 const code = 'console.log(`Привет!`)';
 vm.runInContext(code, sandbox);
  6. Внутри Webpack 17 !// 1.Создаём iframe, прячем и добавляем в

    документ var iframe = document.createElement('iframe'); if (!iframe.style) iframe.style = {}; iframe.style.display = 'none'; document.body.appendChild(iframe);
  7. Внутри Webpack 18 !// 2. Записываем/переопределяем свойства window в iframe

    var win = iframe.contentWindow; 
 forEach(Object.keys(context), function (key) { win[key] = context[key]; });
  8. Внутри Webpack 19 !// 3. Запускаем код в контексте iframe


    var res = win.eval.call(win, this.code);
 !// 4. Удаляем iframe
 document.body.removeChild(iframe);
  9. Как проверка выглядит в коде 38 // Задаём стили в

    эталоне
 dom.changeEtalon(function () {
 this.css(function () {
 this.append('.land { display: grid }');
 this.append('.land { grid-template-columns: 100px 100px 10 });
 });
 // Сравниваем стили в документе студента с эталоном
 return dom.node('.land').hasSame(
 '{display,grid-template-columns}'
 );
  10. Как выглядит AST 13 for var 1 i for (


    var i = 1;
 i <= 10;
 i++
 ) { }
  11. Как выглядит AST 13 for var 10 <= i 1

    i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  12. Как выглядит AST 13 for var 10 i ++ <=

    i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  13. Как выглядит AST 13 for var 10 i {} ++

    <= i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  14. Как выглядит проверка 13 for var 10 i {} ++

    <= i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  15. Как выглядит проверка 13 for var 10 i {} ++

    <= i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { } 10 <= i 10
  16. Как проверка выглядит в коде 13 // Задаём шаблон для

    проверки AST
 goal('for.i').code(
 '"#builtin.anything"; for (var i = 1; "#f.cond"; "#f.inc") { ) .fragment('f.cond').code('i <= 10', '10 >= i', 'i < 11', '11 .fragment('f.inc').code('i++', '++i', 'i += 1', 'i = i + 1',
  17. Как проверка выглядит в коде 13 // Переопределяем значения переменных

    в коде пользователя
 this.initializeVariables({
 encodedMessage: [12, 53, 57, 58, 38, 66, 44, 48, 52, 45, 38, });
 
 this.assertHiddenEquals({
 decodedMessage: 'Лучше котлета в зубах, чем синица в небе.'
 });
  18. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } .land { grid-template-areas: "w w l l" "w w l l" "g g l l" "r r l l"; } $%
  19. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } .land { grid-template-areas: "w w l l" "w w l l" "g g l l" "r r l l"; } $% Сервер
  20. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } .land { grid-template-areas: "w w l l" "w w l l" "g g l l" "r r l l"; } $% Сервер
  21. Phantom JS – Webkit – Редко обновлялся – Отставал от

    текущих версий браузеров – Перестал поддерживаться 13
  22. Phantom JS – Webkit – Редко обновлялся – Отставал от

    текущих версий браузеров – Перестал поддерживаться 13 Puppeteer – Chromium – Часто обновляется – Соответствует текущим браузерам – Развивается
  23. iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn" type="button">


    +
 !</button> Как выглядит проверка transition
  24. iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn" type="button">


    +
 !</button> Как выглядит проверка transition
  25. iframe iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn"

    type="button">
 +
 !</button> Как выглядит проверка transition
  26. iframe iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn"

    type="button">
 +
 !</button> Как выглядит проверка transition
  27. iframe iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn"

    type="button">
 +
 !</button> Как выглядит проверка transition
  28. Как это выглядит в коде 13 !// Задаём финальное состояние

    эталону
 dom.changeEtalon(function () { this.html(function () {
 this
 .find('<button class="btn" type="button">')
 .replace('<button class="btn btn-active" type="button">' });
 this.css(function () {
 this.append('.btn-active { color: #ffffff; transform: rota });
 });
  29. Как это выглядит в коде 13 !// Обнуляем время трансформации,

    добавляем класс кнопке
 dom.changeUserFrame(function () {
 this.css(function () {
 this.append('.btn {transition-duration: 0s;}');
 this.querySelector('.btn').classList.add('btn-active');
 });
 });
 return dom.userFrame() !// Сравниваем два узла
 .node('.btn-active')
 .hasSame('{color, transform}');
  30. Как это выглядит в коде 83 this.setAnswers([{ !// Номер цели

    и вкладка редактора
 goal: 1, editor: 'js', data: function () {
 this
 !// Текст подсказки
 .tooltip('Заменяем сравнение на строгое') .at(3, 13) !// Позиция курсора .add('='); !// Что делаем в коде
 }
 }]);