EmDash 1.2 wyszedł 6 października 2026, pięć dni po wersji 1.1. To duże wydanie: według oficjalnej zapowiedzi 100 scalonych pull requestów, w tym od 21 osób spoza głównego zespołu. Zapowiedź opisuje główne funkcje: nowy edytor, wideo, paginację i zmianę domeny. Ja przejrzałem cały changelog pakietów emdash, @emdash-cms/admin i @emdash-cms/cloudflare i wybrałem drobniejsze rzeczy, które łatwo przeoczyć, a które mają znaczenie, szczególnie na Cloudflare Workers i D1. Na końcu zajrzałem do otwartego PR-a z wydaniem 1.3.0, żeby sprawdzić, co jest w kolejce.
Najważniejsze w 1.2 w skrócie
- Nowy edytor treści. Tytuł jest dużym nagłówkiem, pod nim edytor bez ramki, a jeden pasek na górze trzyma Live View, Preview i Publish. Slash menu podpowiada skróty Markdown i rozumie skróty typu
/bl. - Blok wideo. Wpisujesz
/videoalbo upuszczasz plik w tekście. Filmy z/_emdash/api/media/file/wreszcie grają w Safari i na iOS, bo trasa obsługuje żądaniaRange(206 Partial Content). - Paginacja list. Kolekcja otwiera się z 20 wpisami zamiast pobierać 100.
- Zmiana domeny z panelu. Okno Change domain w Settings → General najpierw sprawdza, czy nowa domena serwuje stronę, potem przestawia Site URL. Jest też mail do użytkowników z nowym adresem i przycisk Continue on, bo passkeye działają tylko na domenie, na której powstały.
- upgrade-emdash.
npx upgrade-emdash@latestaktualizuje wszystkie paczki EmDasha i zapisuje.emdash/UPGRADE.mdz wpisami changeloga, które przeskakujesz. To dobry wsad dla agenta AI robiącego aktualizację. - Brak migracji bazy. Między 1.1.0 a 1.2.0 nie doszła żadna migracja rdzenia, więc aktualizacja nie zmienia schematu D1.
Smaczki z changeloga 1.2
Cloudflare Workers i D1
- Cron mieści się w limicie planu Free (#3861). Cron uruchamiany co minutę na zimnym izolacie potrafił przekroczyć 10 ms CPU z planu Workers Free. Sprzątanie systemowe chodzi teraz raz na godzinę. Co minutę zostają tylko publikacja zaplanowanych wpisów, zadania cron wtyczek i heartbeat. Znam ten limit z własnych pomiarów, więc to dla mnie jedna z ważniejszych poprawek.
- Log 404 nie zjada budżetu odczytów D1 (#3753). Wcześniej co minutę cron skanował całą tabelę
_emdash_404_log, także gdy nie było czego usuwać. Teraz sprawdza ograniczoną próbkę. - Koniec z „too many SQL variables”. D1 ma limit parametrów w zapytaniu i w 1.2 poprawiono dwa miejsca, które go przekraczały: przypisanie więcej niż ~30 kategorii lub tagów do wpisu (#3889, psuło to też import z WordPressa) oraz
ctx.storage.<kolekcja>.getMany()/deleteMany()we wtyczkach przy ponad 98 identyfikatorach (#3776). - Zapisy „po odpowiedzi” wreszcie się kończą. Liczniki przekierowań, log 404 (#3287), data ostatniego użycia tokenu API (#3767) i hooki
comment:afterCreate(#3631) były urywane, bo Worker kończył pracę zaraz po wysłaniu odpowiedzi. Teraz działają przezafter()/waitUntil. - Szybszy zimny start (#3573, #3574, #3575). Sprawdzenie bazy idzie równolegle ze startem runtime'u, ustawienia providerów wtyczek ładują się razem z innymi odczytami startowymi, a
getWidgetAreas()zrobi o jedno zapytanie mniej dla niezalogowanych.
Cache i bezpieczeństwo
- Route cache nie trzyma już stron zalogowanych (#3898). Z
cacheCloudflare()strona wyrenderowana dla zalogowanego użytkownika (np. formularz komentarza z jego imieniem i e-mailem) mogła trafić do cache'u i pokazać się anonimowym odwiedzającym. Jeśli używasz Workers Cache z regułą typu/[...slug], zaktualizuj. - Stored XSS przez pasek edycji (#3681). EmDash wstawiał toolbar przed pierwszym
</body>w odpowiedzi, a Astro nie escapuje<i>w atrybutach. Tekst alternatywny obrazka zawierający</body>przesuwał więc pasek do środka atrybutu. Autor mógł w ten sposób uruchomić skrypt u każdego zalogowanego redaktora, a przytoolbar: "client"u każdego odwiedzającego. To najmocniejszy argument za aktualizacją. - ETag i 304 dla mediów (#3855). Pliki mediów i transformacje
/imagemająETagiLast-Modified, więc przeglądarka może odświeżyć cache jednym żądaniem warunkowym zamiast pobierać plik od nowa. - Konflikty zapisu (#3930).
PUTz_revnie nadpisze już zmiany, którą ktoś inny zapisał w trakcie przetwarzania żądania.
Wtyczki
plugin:installiplugin:activatewreszcie się uruchamiają (#3785) dla wtyczek z tablicypluginswastro.config.mjs. Jeśli planowałeś crona wplugin:activatei nic się nie działo, to był ten błąd.- Hooki
media:beforeUploadimedia:afterUploaddziałają przy uploadzie z panelu (#3914). - Grupy w menu bocznym (#3546). Strony admina wtyczek można wkładać do zwijanych folderów obok kolekcji.
- Szczegóły błędów (#3602).
PluginRouteError.badRequest(message, details)zwracadetailsdo klienta, więc formularz może pokazać, które pole jest złe.
Treść i SEO
- Sitemapy powyżej 50 000 wpisów (#3806). Wcześniej nadmiarowe wpisy po cichu wypadały. Teraz każda
/sitemap-{kolekcja}.xmlma do 2000 wpisów i ciąg dalszy w-2.xml,-3.xmlitd. Do tego/sitemap-0.xml, o którą pytają crawlery, zwraca 404 zamiast 500 (#3595). - Podgląd szkiców na listach (#3802).
getEmDashCollection()w trybie edycji i podglądu pokazuje teraz wersję roboczą, tak jakgetEmDashEntry(). Edycje inline na stronie listy nie wyglądają już, jakby się cofnęły po zapisie. - Brakujący prefiks języka w
entry.id(#3922). Na stronach wielojęzycznych z D1entry.idczasem nie miał prefiksu typuen/, co psuło linki. - Import z WordPressa jest lepszy. Tabele z Classic Editora zostają tabelami (#3762), zaplanowane wpisy przychodzą jako zaplanowane (#3895), a linki do starych uploadów poza blokami obrazków są przepinane na zaimportowane media (#3896).
Panel i tłumaczenia
admin.locales(#3056). Ograniczasz panel do języków, których używasz, np.admin: { locales: ["en", "pl"] }, i bundle admina robi się mniejszy. Niezależnie od tego date picker ładuje lokalizację na żądanie, co daje około 220 KB mniej JavaScriptu (#3923).- Nowe języki: hebrajski z układem RTL (#3293), portugalski europejski (#3796), kompletny tajski, niemiecki, kataloński i chiński tradycyjny.
- Domyślne wartości pól (#3758). Pole boolean z
defaultValue: truew nowym wpisie startowało wyłączone. Już nie. syncName: false(#3875) dla Cloudflare Access i innych zewnętrznych providerów. Imię zmienione w panelu nie jest już nadpisywane przy każdym żądaniu.
Co szykuje 1.3.0
Wydanie 1.3.0 czeka w otwartym PR-ze z release'em , który Changesets aktualizuje przy każdym scaleniu. Lista może się więc jeszcze zmienić, ale na dziś wygląda tak.
Pełne polskie tłumaczenie panelu (#3970)
Najważniejsza rzecz dla polskich użytkowników. Do tej pory 2255 z 3384 tekstów panelu spadało do angielskiego. W 1.3 polski panel ma być kompletny: kalendarz publikacji, edytor, zmiana domeny, bylines, relacje, transfer strony, kopie zapasowe, rejestr wtyczek i konfiguracja passkeyów.
Edycja wizualna dogania panel
- Edytor rich text na stronie dostaje ten sam pasek zaznaczenia i slash menu co panel (#4117) oraz wybór i pasek narzędzi obrazków (#4137).
- Puste pola Portable Text, np. treść nowego wpisu, da się wreszcie pisać bezpośrednio na stronie (#3942).
- Zapis przy utracie fokusu nie dodaje już nowej rewizji przy każdym kliknięciu obok pola, tylko podmienia szkic, tak jak autosave w panelu (#3942).
- Kliknięcie pola stawia kursor w miejscu kliknięcia zamiast zaznaczać cały tekst, przez co pierwszy znak kasował całą wartość (#4014).
Cache: mniej purge'owania, poprawne przekierowania
- Utworzenie lub zduplikowanie wpisu nie czyści już cache'u stron (#4128). Nowy wpis jest szkicem, którego żadna publiczna strona nie pokazuje, więc listy kolekcji zostają w cache'u do następnej zmiany w opublikowanej treści.
- Nowe przekierowanie czyści z Workers Cache stronę pod tą ścieżką (#3982). Do tego middleware przed zapisem do route cache sprawdza, czy pod tym adresem nie ma już przekierowania (#3997), bo izolat ze starymi regułami potrafił z powrotem wpisać do cache'u starą stronę.
- Nieudany purge nie zgłasza już błędu zapisu, skoro zmiana i tak się zapisała (#3987).
D1 i migracje
emdash migrate --take-over-lock <id>(#4068) stosuje oczekujące migracje pod zablokowanym lockiem D1, bez zwalniania go. Przy--release-locki ponownymmigrateWorker w trybieautomógł przejąć wolny lock w międzyczasie.- Migracja normalizacji dat da się wznowić (#4072). Na dużych bazach D1 trwała godziny i po każdym przerwaniu zaczynała od nowa. Teraz zapisuje w partiach i kontynuuje od ostatniej.
getComments()w jednym zapytaniu (#3907), gdy zatwierdzone komentarze mieszczą się na jednej stronie. Plus do dwóch zapytań mniej przy zimnym starcie dla stron z rejestrem wtyczek (#3584).- Ostrzeżenie o niezgodnych wersjach (#4058).
astro buildostrzeże, gdy@emdash-cms/cloudflarema inną wersję niżemdash. Adapter zależy od dokładnej wersji rdzenia, więc aktualizacja tylko jednego pakietu instaluje drugą kopięemdash. - Filtr
wherez długimi tablicami (#3265).{ in: [...] }z długą listą nie wywala się już na limicie parametrów D1.
Uprawnienia i MCP
- Contributor wreszcie może zapisywać własne szkice (#4133). Wcześniej mógł utworzyć wpis, ale następny zapis kończył się błędem 403.
- Narzędzie MCP
content_createprzyjmujeseoipublishedAtw jednym wywołaniu (#4102), więc agent nie musi już robić osobnegocontent_update. - Narzędzia MCP wtyczek z ID typu
@acme/calendardostają nazwyacme__calendar__<tool>(#988). Jeśli masz zapisane wywołania po starych nazwach, trzeba je zmienić.
Panel i reszta
- Edytor menu pozwala zmienić nazwę menu i ustawić klasy CSS pozycji (#3969).
- Byline'y tworzysz z wpisu tym samym pełnym formularzem co na stronie Bylines (#4050).
- Otwarcie wpisu bez żadnej edycji nie zapisuje już szkicu (#4035). Dotyczyło to m.in. treści zapisanych przez MCP lub
markdownToPortableText. - Wyczyszczone pole liczbowe zapisuje się jako puste, a nie
0(#3791). Wyczyszczony opcjonalny URL tonull, a nie pusty string odrzucany przy walidacji (#4076). - Import z WordPressa przez wtyczkę EmDash Exporter zachowuje pola ACF (#4092). Import XML pomija typy
acf_field(#4090), a importer wysyła nagłówekUser-Agent, bo niektóre hostingi blokowały puste (#4113). - Wyszukiwanie pełnotekstowe nie traktuje już słów „and”, „or”, „not” czy „near” jako operatorów FTS5 (#3202).
- Nowe tłumaczenia: chorwacki (#3934), uzupełniony francuski, niemiecki, hindi i szwedzki, a także pierwszy katalog włoski.
Czy aktualizować?
Do 1.2 tak, i to głównie z powodu bezpieczeństwa: XSS przez pasek edycji (#3681) i strony zalogowanych w route cache (#3898) to błędy, których nie chcesz mieć na produkcji. Na Workers Free dochodzi do tego cron mieszczący się w limicie CPU. Aktualizacja nie zawiera migracji bazy, a npx upgrade-emdash@latest przygotuje listę zmian do przejrzenia. Pamiętaj tylko o podbiciu emdash i @emdash-cms/cloudflare razem. Od 1.3 dostaniesz o tym ostrzeżenie przy buildzie, w 1.2 musisz pilnować tego sam.
Aktualizacja emdashcms.pl: poszło gładko
emdashcms.pl działa już na 1.2.0. npx upgrade-emdash@latest podbił emdash i @emdash-cms/cloudflare (razem, jak trzeba) oraz wtyczkę webhook-notifier. Nie dodał żadnej migracji, a z 68 wpisów changeloga w wygenerowanym .emdash/UPGRADE.md żaden nie wymagał zmian w kodzie strony.
Przy okazji przestawiłem język treści na polski. W astro.config.mjs wystarczy i18n: { defaultLocale: "pl", locales: ["pl"] }. Przy jednym języku EmDash nie włącza filtrowania po języku ani prefiksów /pl/ w adresach, więc nowe wpisy dostają tylko etykietę pl. Istniejące treści trzeba przestemplować samemu, jednym UPDATE na tabelach z kolumną locale, bo panel tego nie zrobi.
Jedyna niespodzianka: upgrader odświeża też skille dla agentów AI w .agents/skills i doinstalowuje nowe (u mnie trzy). Przejrzyj diff przed commitem.
Pomiary przed i po: 10 rund na stronę, z pominięciem cache, z przerwą 1,5 s między żądaniami (Workers Free, D1).
| Strona | render p50 · 1.1 | render p50 · 1.2 | TTFB p50 · 1.1 | TTFB p50 · 1.2 |
|---|---|---|---|---|
| Strona główna | 94 ms | 108 ms | 335 ms | 380 ms |
| Kategoria | 91 ms | 101 ms | 336 ms | 362 ms |
| Lista wpisów | 102 ms | 95 ms | 338 ms | 337 ms |
| Wpis | 114 ms | 122 ms | 360 ms | 403 ms |
Różnice wynoszą od −7 do +14 ms, a p95 skacze w tych samych seriach o 100–200 ms, więc to szum. Pomiar po aktualizacji robiłem chwilę po deployu, na świeżych izolatach, które zwykle są trochę wolniejsze. Wszystkie 80 żądań zwróciło 200. Wniosek: 1.2 nie przyspiesza ani nie spowalnia renderowania. Aktualizujesz dla poprawek bezpieczeństwa i spokoju.
Brak komentarzy