Paperless Forest

Лента

Как переиспользовать код с помощью dataviewjs

#dataview #dataviewjs #Obsidian

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

Раньше я использовала для этого плагин CustomJS, но теперь выяснила, как можно обойтись стандартным функционалом Dataview.

Для этого используется функция dv.view().

Сначала создаём файл с расширением .js, например, my_сode.js, и кладём его в любое место в своём хранилище Обсидиана. Для примера положим его в папку scripts. Пишем в нём весь код, который хотим переиспользовать. Например, напишем там следующий код:

dv.paragraph("Hello world!")

Затем в заметке в блоке dataviewjs пишем:

await dv.view("scripts/my_code")

При этом весь код, содержащийся в файле my_code.js автоматически исполняется и рендерится. Но что если мы не хотим ничего сразу рендерить, а хотим вернуть какие-то функции или переменные, которые можно использовать позже? Это можно сделать следующим образом.

В файле my_code.js пишем:

this.myFunc = (x) => {
	dv.paragraph(x)
}

this.myVar = "Hello world!"

И в заметке в блоке dataviewjs пишем:

await dv.view("scripts/my_code")

myFunc(myVar)

Подобным же образом можно переиспользовать любые функции или переменные.

Замечание: При таком способе все функции и переменные присваиваются глобальному объекту window, что не очень безопасно, потому что можно случайно перезаписать какие-то существующие свойства или методы. Кажется, что безопаснее было бы использовать промежуточный объект.

Например, в файле my_code.js пишем:

const myFunc = (x) => {
	dv.paragraph(x)
}

const myVar = "Hello world!"

this.myObject = {myFunc, myVar}

И в заметке в блоке dataviewjs пишем:

await dv.view("scripts/my_code")

const {myFunc, myVar} = myObject

myFunc(myVar)

У объекта myObject должно быть уникальное имя, не совпадающее ни с одним из свойств объекта window, но с одним объектом это легче проконтролировать, чем со множеством функций и переменных, которые мы можем использовать.

Можно также использовать класс вместо объекта. В файле my_code.js пишем:

this.myClass = class myClass {
	myFunc() {
		dv.paragraph("Hello world!")
	}
}

И в заметке в блоке dataviewjs пишем:

await dv.view("scripts/my_code")

const newClass = new myClass

newClass.myFunc()

Оставить комментарий


Синхронизация через Syncthing без интернета

#синхронизация #syncthing #Obsidian

Я наконец дозрела попробовать Syncthing для синхронизации Обсидиана. До этого меня останавливало, что там надо, чтобы устройства были в одной сети, а как это организовать вне дома без танцев с бубном, я не знала (всё, что там про какие-то сервера и порты вызывает у меня короткое замыкание в мозгу).

Моя проблема в том, что мне надо синхронизировать файлы с рабочим компом. На работе у меня нет вайфая, стоит файервол с кучей ограничений, почти все настройки намертво заблокированы, а периодически админы вообще отключают интернет, мол, нефиг расходовать рабочий трафик попусту. Из-за этого большинство методов синхронизации у меня там не работало вообще или работало плохо (мне удалось настроить гит, но он был очень медленный). У меня была мысль раздать вайфай с телефона, но как назло мой провайдер недавно сделал раздачу интернета с телефона платной и жутко дорогой.

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

  • отключаем мобильный интернет на телефоне (чтобы не расходовать платный трафик);
  • включаем на телефоне точку доступа;
  • подключаем компьютер к этой точке доступа как к вайфаю;
  • запускаем Syncthing.

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

Оставить комментарий


Кастомные чекбоксы в Obsidian

#Obsidian #css #checkboxes

В Обсидиане очень удобно использовать свои собственные чекбоксы, например, такие:

Есть темы для Обсидиана, которые уже поддерживают некоторые из подобных чекбоксов, но можно назначить свои собственные при помощи css:

input[data-task="h"]:checked,
li[data-task="h"] > input:checked,
li[data-task="h"] > p > input:checked {
  --checkbox-marker-color: transparent;
  border: none;
  border-radius: 0;
  background-image: none;
  background-color: currentColor;
  -webkit-mask-size: var(--checkbox-icon);
  -webkit-mask-position: 50% 50%;

  color: var(--color-red);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='18' height='18' %3E%3Cpath fill='none' d='M0 0H24V24H0z'/%3E%3Cpath d='M12.001 4.529c2.349-2.109 5.979-2.039 8.242.228 2.262 2.268 2.34 5.88.236 8.236l-8.48 8.492-8.478-8.492c-2.104-2.356-2.025-5.974.236-8.236 2.265-2.264 5.888-2.34 8.244-.228z'/%3E%3C/svg%3E");
}

Ссылки на svg-иконки, которые подставляются в свойство “-webkit-mask-image”, можно брать, например, тут: Remix Icon

Если надо сделать чекбокс некликабельным:

.HyperMD-task-line[data-task="h"] > .task-list-label, 
input[data-task="h"],
li[data-task="h"] > input, 
li[data-task="h"] > p > input
 {
  pointer-events: none;
}

Шаблон этого сайта поддерживает некоторые кастомные чекбоксы, но не все:

  • [n]
  • [r]
  • [>] [>]

Безопаснее использовать буквы, а не символы.

Оставить комментарий


Трёхактная структура

#писательство

  • #NB Шпаргалка для писателя

1 акт #

  • 1% - Крючок

    • Открывающая сцена, которая должна зацепить читателя.
  • Экспозиция

    • Читатель знакомится с миром, героями и конфликтом. Обозначаются цели и ставки.
  • 12% - Побуждающее событие

    • Первое активное вмешательство конфликта в Нормальный мир. зов приключений для героя.
  • Завязка

    • Складываются условия для окончательного вступления героя в конфликт. Нарастает напряжение.
  • 25% - Первая переломная точка

    • Герой покидает Нормальный Мир, получает цель и вступает в конфликт.

2 акт #

  • Реакция

    • Герой пытается приспособиться к новым обстоятельствам.
  • 37% - Первая точка фокусировки

    • Напоминание о конфликте и появление подсказок.
  • Осознание

    • Герой всё больше узнаёт об обстоятельствах и конфликте.
  • 50% - Центральная точка

    • Момент истины. Герою раскрывается природа конфликта.
  • Активное действие

    • После получения ключевой информации герой переходит к решительным действиям.
  • 62% - Вторая точка фокусировки

    • Предвестие катастрофы и напоминание о ставках.
  • Обновлённая атака

    • Герой действует ещё активнее и достигает ложной победы.

3 акт #

  • 75% - Третья переломная точка

    • Ложная победа сменяется катастрофой. герой делает окончательный выбор и должен чем-то пожертвовать или что-то потерять. Самый тёмный момент.
  • Восстановление

    • Герой восстанавливается после катастрофы, переосмысливает свои выборы и утверждается в своей конечной цели.
  • 88% - Начало кульминации

    • Герой вступает в финальное противостояние с антагонистической силой.
  • Кульминация

    • Высшее проявление конфликта, приводящее к его разрешению. Стреляют все ружья, даются ответы на все вопросы. Финальная битва, объяснение, разгадка.
  • 98% - Кульминационный момент

    • Герой достигает своей цели или окончательно теряет её. Конфликт разрешается.
  • Развязка

    • Передышка после кульминации и картина её последствий.

Оставить комментарий


Obsidian QuickAdd - как запускать скрипты

#Obsidian #QuickAdd

Плагин для Обсидиана QuickAdd позволяет автоматически создавать заметки, но ещё его можно использовать в качестве запускалки скриптов.

Javascript #

  • Создать файл в формате js и сохранить его в любом месте хранилища.
  • В файле написать код:
module.exports =  async (params) => {
    
  /Мой код. В нём можно использовать API Обсидиана и самого плагина./

}
  • В настройках QuickAdd создать макрос и в настройках макроса выбрать созданный скрипт.
  • Не забыть отметить значок молнии рядом с названием макроса, чтобы активировалась команда. Потом эту команду можно подвязать на хоткей или добавить кнопочку с помощью плагина Commander.

Другие языки и прочие файлы #

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

  • Нужно добавить файл, который мы хотим запустить, в хранилище. Например, это может быть bash-файл, который коммитит и пушит заметки на гитхаб.
  • Создать js-скрипт и макрос по инструкции выше.
  • В js-файле написать код:
module.exports =  async (params) => {
  
  let scriptPath = "\\scripts\\myFile.sh" /Здесь вместо моего примера надо указать путь к файлу, который мы хотим запустить. Путь указывается относительно хранилища. Обязательно надо эскейпить обратные слэши/

  let cmd = this.app.vault.adapter.basePath + scriptPath
  const { promisify } = require('util'); 
  const exec = promisify(require('child_process').exec); 
  await exec(cmd);

}

Этот скрипт запускает файлы на Windows. В других системах код может отличаться, в частности, путь будет записываться прямыми слэшами, но может, есть и другие нюансы, не знаю. Поскольку мы не прописываем напрямую путь к хранилищу, а находим его с помощью кода, этот скрипт может работать на разных устройствах.

Запрашивать подтверждение перед выполнением скрипта #

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

module.exports =  async (params) => {

  const { quickAddApi: { yesNoPrompt } } = params;
  const runScript = await yesNoPrompt("Выполнить скрипт?");

  if (runScript) {

    /Здесь пишем код, который будет выполняться при подтверждении/
  }
}

Вызывать системные команды Обсидиана изнутри скрипта #

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

module.exports =  async (params) => {

  /Какой-то код/
  
  await app.commands.executeCommandById(id) /где id  это id конкретной команды/
  
  /Какой-то код/

}

Чтобы узнать id команды, можно открыть консоль и написать код:

console.log(app.commands.commands)

Это выведет список всех доступных на данный момент команд, включая команды из установленных плагинов, где указаны их названия и id.

Пример — скрипты для обновления вкладок #

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

Скрипт, чтобы обновить текущую активную вкладку:

module.exports =  async (params) => {

   await app.workspace.activeLeaf.rebuildView()
}

Скрипт, чтобы обновить все открытые вкладки:

module.exports =  async (params) => {

  await app.workspace.rightSplit.children.forEach(pane => {

    pane.children[pane.currentTab].rebuildView()
  })

  await app.workspace.leftSplit.children.forEach(pane => {

    pane.children[pane.currentTab].rebuildView()
  })

  await app.workspace.rootSplit.children.forEach(pane => {

    pane.children[pane.currentTab].rebuildView()
  })
}

Обновление вкладок может быть полезно при использовании некоторых плагинов, например Dataview и Supercharged Links, потому что они не всегда обновляют вид в реальном времени.

Оставить комментарий


Менеджер коллекций для Покетбука

##технологии ##IT-проекты

У меня есть читалка Покетбук, и в ней можно сортировать книги по полочкам. Но массово это в самой читалке делать неудобно, так что я накодила вот такую прогу: PocketBook Collection Manager.

Это ученический проект, который нуждается в доработке, но дело своё делает.

Оставить комментарий