Простенькие заметки на $mol

от автора

картинка для привлечения внимания. чорт. надеюсь никто не читает альты..
Начало пути капитана $mol’a! Шта?..

Здравствуйте, меня не зовут Дмитрий Карловский и я… решил написать простенькие заметки на $mol в несколько итераций:

  1. Настраиваемся
  2. Возводим скелет
  3. Сохраняемся
  4. Шаримся
  5. Пакуемся

0. Настраиваем рабочее окружение MAM

парой команд — это делается один раз под все проекты:

git clone https://github.com/hyoo-ru/mam.git cd mam npm install

Запускаем дев сервер:

npm start

Он заиграет на 9080 порту http://127.0.0.1:9080, а нам можно начинать смолить..

Возводим скелет

Создаём наш проект: в склонированной папке mam создаем папки habr/notes

В нём создём точку входа habr/notes/index.html:

<!doctype html> <html mol_view_root>     <head>         <meta charset="utf-8" />         <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">     </head>     <body mol_view_root>         <div mol_view_root="$habr_notes"></div>         <script src="web.js" charset="utf-8"></script>     </body> </html>

Заметили $habr_notes? Тут везде fqn обращения (имя = путь), а в mol_view_root мы указываем наше приложение. Точнее, компонент — здесь это одно и то же по смыслу, только мы можем вкладывать компоненты друг в друга и делегировать/рекомпозировать/хакать их свойства между собой.

Что же, создадим сам компонент habr/notes/view.tree:

- это комментарий, ах да, следим за табами $habr_notes $mol_page

Шпаргалка по синтаксису и страшная статья о view.tree

В браузере можем перейти по адресу http://127.0.0.1:9080/habr/notes и увидим зачаток нашего приложения:

*гифка*

Придадим форму, подправив файл view.tree:

- мы отнаследовали $habr_notes от $mol_page $habr_notes $mol_page     - в свойство body мы положили массив /     body /         - в этот массив мы вложили компонент $mol_textarea и назвали его Input         <= Input $mol_textarea

О, теперь у нас появилось текстовое поле ввода:

*гифка*

Но наш введенный текст теряется при обновлении страницы, давайте это изменим.

Сохраняемся…

в localStorage

Подправим наш view.tree файл до такого содержания:

$habr_notes $mol_page     body /         <= Input $mol_textarea             - переопределяем наше свойство value             value?val <=> text?val \

подробнее про свойства компонента $mol_textarea туть

Собственно на этом момент можно уже начать задаваться вопросом какого черта тут происходит и зачем нужны эти view.tree файлы.

view.tree — это DSL, транслирующийся в ts.

Пример выше преобразится в такой код:

namespace $ {     export class $habr_notes extends $mol_page {          /**          * ```tree          * body / <= input          * ```          */         body() {             return [                 this.Input()             ] as readonly any[]         }          /**          * ```tree          * text?val \          * ```          */         @ $mol_mem         text(val?: any) {             if ( val !== undefined ) return val as never             return ""         }          /**          * ```tree          * Input $mol_textarea value?val <=> text?val          * ```          */         @ $mol_mem         Input() {             const obj = new this.$.$mol_textarea()              obj.value = (val?: any) => this.text(val)              return obj         }     }  } 

Вы можете сами поиграться в песочнице.

Зачем он нужен? Для разделения мух и котлет.

С помощью view.tree мы декларативно описываем наш интерфейс.
С помощью view.tree.ts мы императивно описываем работу самой логики.

Из view.tree сборщик сгенерировал шаблонный код в файл habr/notes/-view.tree/view.tree.ts.

При обновлении view.tree файла, файл выше обновляется сам.

Зачем он нужен? Для переопределения!

Можем заметить, что код выше сгенерировался в неймспейсе $.

Свою логику мы будем описывать в неймспейсе $.$$ — то есть, «перекрывая» своей логикой.

Вернёмся же к нашему коду.
Создаём файл habr/notes/view.tree.ts:

namespace $.$$ {     export class $habr_notes extends $.$habr_notes {         @ $mol_mem         text(val?: any) {             if ( val !== undefined ) return val as never             return ""         }     } } 

Тут я перенёс text(val?: any) — функция-заглушка, сгенерированная из view.tree файла с навешенным декоратором @ $mol_mem (от memoization)

Это канал — он возвращает значение, при вызове его без параметра, а при вызове с параметром он указывается в качестве значения.

Почему оно работает?

Мы открыли наше приложение, поле ввода запросило значение из функции text, функция text вернуло пустую строку.

Мы ввели первый символ, в функцию text передалась нажатая клавиша, функция text сохранила её.

Мы вводим последующие символы, они запоминаются и результат функции text возвращается в поле ввода.

Ага, значит сюда и можно подвязать сохранение данных в localStorage.

В $mol есть модуль $mol_state_local — реактивная обертка над localStorage — ей и воспользуемся:

namespace $.$$ {     export class $habr_notes extends $.$habr_notes {         @ $mol_mem         text(val?: any) {             return $mol_state_local.value('note', val) || ""         }     } } 

Проверяем… работает! После перезагрузки страницы наш введённый текст сохраняется.

**гифка**

Я создал репозиторий с веткой stage-1, действия выше воспроизведены в нём — можно сравниться.

Что же, осталось научиться шариться данными!

Собственно,

Шаримся

заметками, используя децентрализованную криптографическую систему, ну а почему нет
¯\(ツ)

Поправим view.tree файл:

$habr_notes $mol_page     - через синк клиент мы обмениваемся данными в сети     yard $hyoo_sync_client     tools /         - через модуль онлайна мы подключаемся к пирам и синхронизируемся         <= Online $hyoo_sync_online             yard <= yard     body /         <= Input $mol_textarea             value?val <=> text?val \             enabled <= i_have_can_mod false 

Опишем логику view.tree.ts:

namespace $.$$ {     export class $habr_notes extends $.$habr_notes {         @$mol_mem         text( val?: any ) {             return this.store().str( val ) || ""         }          @$mol_mem         store() {             // через модуль клиента мы обращаемся к хранилищу (миру),             // используем тип $hyoo_crowd_reg - он позволяет атомарно хранить значения (строки, числа, булы)             // запрашиваем участок с указанным id             return this.yard().world().Fund( $hyoo_crowd_reg ).Item( this.current_note_id() )         }          @$mol_mem         current_note_id() {             // мы считываем id заметки из урла, или, если пустой, указываем новый свой             const id = this.$.$mol_state_arg.value( '' ) || this.yard().land_grab().id()             // задаём в урл текущий id - чтобы мы могли его сразу же скопировать             this.$.$mol_state_arg.value( '', id )             return id as $mol_int62_string         }          @$mol_mem         i_have_can_mod() {             // проверка наличия прав на редактирование             return this.yard().land( this.current_note_id() ).allowed_mod()         }     } } 

Вот как это выглядит:

ля, работает

Для сверки, ветка stage-2.

А может вам рюшечки?

Добавим поддержку тем тройкой строк кода:

$habr_notes $mol_page     plugins /         - включаем поддержку смены тем         <= Theme $mol_theme_auto     yard $hyoo_sync_client     tools /         <= Online $hyoo_sync_online             yard <= yard         - добавляем кнопку-переключалку         <= Lighter $mol_lights_toggle     body /         <= Input $mol_textarea             value?val <=> text?val \             enabled <= i_have_can_mod false 

Вот так это выглядит:

Или ехать?

А может сделаем наше pwa offline-first?

Пфф: создаем в той же директории файл view.meta.tree:

include \/mol/offline/install

Одной строчкой мы подключили Service Worker, который закеширует наше приложение и позволит работать ему при отсутствии интернетов.

Зачем? CROWD, который мы используем, автоматически синхронизируется с внешним миром при потери и появлении интернета.

Для сверки, ветка stage-3.

Пакуемся

мы командой:

npm start habr/notes

Наш статический бандл расположится в папке habr/notes/-/ — его и можно хостить.

В ходе всех вышеописанных шагов можно заметить появившиеся папки:

  • -/ — наш бандл
  • -view.tree/ — наш переопределяемый код

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

Например, файл .gitignore будет таков:

-*

Отвлеклись, задеплоимся на какой-нибдь фапхаб с возможностью хостить статические странички — тот же Github Pages.

Выгрузим содержимое папки - в ветку gh-pages и можем лицезреть результаты наших работ по ссылке: https://koplenov.github.io/habr-notes/#!=sxktck_j3e02v

Схожее по теме:

Ссылка на доку туть, а мы обитаем туть..


ссылка на оригинал статьи https://habr.com/ru/articles/732934/


Комментарии

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

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