Блог

Природно друштво

Категорије:
  • ажурирања сајта

Пажљивији пратиоци ове странице су сигурно приметили додатно дугме у app-bar-у, које није радило ништа значајно. Данас сам започео додавање подршке за пријављивање преко друштвених мрежа мом сајту. Ако сада притиснете дугме „ Пријава“, на дну екрана ће се отворити панел сличан овоме:

Панел за пријављивање преко друштвених мрежа

У наредном периоду ћу радити на подршци за логовање. ETA unknown.

Гистови у Markdown-у

Категорије:
  • ажурирања сајта

Ових дана после мање паузе радим на неколико делова мог сајта, па једва стижем да нешто и напишем о ономе шта додам. Недавно сам тако додао подршку за учитавање гистова у чланке на овом блогу.

За оне који не знају шта су то гистови (gists), ради се о фајловима, или деловима фајлова, са изворним кодом које је могуће делити и чак fork-овати као било који други фајл на GitHub-у. Просто поставите мини-репо са једним или више фајлова и поделите његов УРЛ. Сјајно! 😃

Ова могућност, која је уједно и тест динамичких компонената о којима сам недавно писао, ми је била посебан изазов и уједно извор материјала за учење Nuxt.js-а. Видећемо које су неке од карактеристичних тачака које сам прешао приликом њеног развоја.

Почетак

Рад са гистовима почињемо посетом УРЛhttps://gist.github.com, где ће они које означимо као јавне бити доступни на адреси облика

https://gist.github.com/[корисничко_име]/[хеш]

Верзији гиста у формату JSON можемо приступити додавањем .json на крај те адресе, дакле:

https://gist.github.com/[корисничко_име]/[хеш].json

Простим позивом this.$axios.$get() или this.$http.$get(), у зависности од тога да ли користимо модул axios или http, учитамо тај JSON и посао је готов, зар не?

Нажалост, то није баш тако. Уколико вам не смета подразумевано HTML форматирање поља div насталог JSON објекта, или чињеница да се сви фајлови заједно налазе у том (скаларном) пољу, и то је довољно. За било шта више, потребно је учитати гист преко API-ја.

API

За просто учитавање довољно је методом GET приступити УРЛ

http://api.github.com/gists/[хеш]

где је [хеш] хеш код вашег гиста, исти као у претходном случају. Резултат је опет JSON објекат, али који укључује фајлове у сировом облику као засебна поља.

Код

Конкретан код сам раздвојио на онај који је оријентисан на податке (Vuex store) и презентациони (компонента Gist). Ево најзанимљивијих делова:

<template>
<!-- ... -->
</template>
<script>
export default {
name: 'Gist',
props: {
gist: { type: Object, default: () => ({}), required: true },
filename: { type: String, default: '', required: true },
highlightedLine: { type: Number, default: 0, required: false },
},
computed: {
gistRawUrl()
{
if (!this || !this.gist || !this.gist.files || this.filename.length==0
|| !this.gist.files[this.filename])
{
return null;
}
return this.gist.files[this.filename].raw_url;
},
gistLines()
{
if (!this || !this.gist || !this.gist.files || this.filename.length==0
|| !this.gist.files[this.filename])
{
return null;
}
return this.gist.files[this.filename].content;
},
},
methods: {
escapeHtml(html)
{
return html
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
},
formatGistLinesAsHtml(lines)
{
let result = '';
if (lines && lines.length>0)
{
let linesArray = lines.split('\n');
for (let line in linesArray)
{
result += (this.highlightedLine==parseInt(line)+1 ?
'<tr class="highlighted-line">\n' :
'<tr>\n') +
'<td class="blob-num js-line-number" data-line-number="' +
(parseInt(line)+1).toString() + '"></td>\n' +
'<td class="blob-code blob-code-inner js-file-line">' +
this.escapeHtml(linesArray[line]) +
'</td>\n' +
'</tr>\n';
}
}
return result;
}
},
};
</script>
<style lang="sass">
@import '~/assets/sass/gist.sass'
</style>
сиров преглед Gist.vue хостује са ❤ GitHub

Gist.vue је компонента за приказивање гиста која је намењена директном укључивању у Markdown фајл. Пошто се фајл преко API-ја учитава као чист текст, даље се са његовим садржајем може радити било шта. На пример, можемо означити појединачне линије или истаћи жељени keyword. Ова компонента се у Markdown фајл укључује на следећи начин:

<component :is="extraComponentLoader"
:filename="'nuxt.config.js'"
:highlighted-line="15"
:gist="gist"></component>

Динамичке руте у статичкој апликацији

Категорије:
  • Програмирање

Наставивши развој сајта, приметио сам једну специфичност Nuxt.js-а. Уколико статички генеришете апликацију преко nuxt generate, а не наведете експлицитно које руте ће бити генерисане, руте са параметрима ће и даље функционисати, али само ако су активиране кроз саму апликацију, преко Vue Router-а (рецимо, <nuxt-link>). Ако унесете УРЛ странице у адресном пољу, или притиснете F5, добићете поруку о грешци, као да рута не постоји!

Проблем

На пример, нека у апликацији имамо следеће странице:

/pages
 ├──/search
 │   └──_docid.vue
 └──index.vue

Нека одговарајући фајлови садрже следећи код:

<!--pages/index.vue-->
<template>
<section>
<nuxt-link to="/search/first">Search: "first"</nuxt-link>
<nuxt-link to="/search/second">Search: "second"</nuxt-link>
</section>
</template>
<script>
export default {
name: "Index"
};
</script>
<!-- ... -->

<!--pages/search/_docid.vue-->
<template>
<div class="search">
<nuxt-link to="/">Back to home</nuxt-link>
<p>{{docBodies[documentId]}}</p>
</div>
<!--doc-->
</template>
<script>
export default {
name: "Search",
asyncData({ params }) {
return {
documentId: params.docid,
docBodies: {
first: "First document",
second: "Second document"
}
};
}
};
</script>
<!-- ... -->

Покретањем nuxt generate без посебно подешене generate секције фајла nuxt.config.js биће генерисана само основна рута, /. Ако приступимо почетној страници, па затим активирамо линк Search: "first", учитаће се страница за претрагу, /search/first. Међутим, притиском на F5 или Ctrl+R страница неће бити исправно учитана. Исто се дешава приступом преко линка /search/first.

Са овим понашањем Nuxt.js-а сам се суочио када сам желео да у мој блог додам подршку за листање свих страница са одређеном ознаком. Рецимо, у мом блогу се за то користи рута /blog/tag/:tagname, и овај чланак ће се појавити у листи чланака на рути /blog/tag/SSR.

Ако негде у апликацији, рецимо у приказу појединачних чланака, позовемо

<nuxt-link :to="`/blog/tag/${tag.name}`">
    {{tag.name}}
</nuxt-link>

све ће функционисати, али не и у поменута два случаја: ако директно посетимо УРЛ или освежимо већ учитану страницу.

Решење

Решење овог проблема је генерисање странице која ће бити „резервна опција“ у случају када задата рута није статички генерисана. Ово се постиже додавањем опције fallback у секцију generate у датотеци nuxt.config.js:

export default {
/*
** Rendering mode
** Doc: https://nuxtjs.org/api/configuration-mode
*/
mode: "universal",
// ...
generate: {
// ***************************************************
// *** Without the next line, F5 on dynamic routes ***
// *** will fail ***
// ***************************************************
fallback: true
},
// ...
};

Ова опција има три могуће вредности:

  • true: fallback руту ће опслуживати фајл /404.html,
  • false: fallback руту ће опслуживати фајл /200.html,
  • '[назив_фајла].html': експлицитно задавање фајла fallback руте.

Ова лако занемарљива опција може представљати разлику између функционалног и нефункционалног сајта.

Нови почетак ✨

Категорије:
  • опште
  • ажурирања сајта

Данас сам завршио следећу етапу у развоју моје личне странице, преласком на нови engine који развијам учећи Nuxt.js. Истовремено, морао сам да трајно или привремено уклоним доста ствари које нису прилагођене новом систему. Неки статички чланци, као што је мој превод ОЈЛ (и верзије 2), су остали.

Поново планирам вођење веб дневника, тј. „блога“. Овај пут сам се одлучио да чланке пишем у Markdown-у који се трансформише у HTML са могућношћу коришћења Vue.js тагова компонената, дакле нечему што више личи на Vue.js template него на чист HTML. Предност овог приступа можда није очита, али то омогућава најразличитије динамичке додатке, почевши од компоненте која би омогућавала додавање анкета, па све до компоненте за исцртавање фрактала или приказивање ASCII art-а.

Са друге стране, Markdown је веома практичан као језик за писање чланака, што знају сви који су имали прилике да коментаришу на Stack Overflow-у или пишу README.md документ на GitHub-у. Његова основна идеја је да буде што ближи ономе како бисмо текст „форматирали“ у обичном .txt документу, за разлику од HTML-а и других језика за означавање. У ери текстуалних терминала се курзив писао уз помоћ подвлака (_) а полуцрна слова уз помоћ [1] звездица (*):

Да _нађемо_ и **изнађемо** решење.

што производи: „Да нађемо и изнађемо решење.“

Верзија Markdown-а коју користим садржи и уводни део сваког чланка у YAML-у, који се назива Frontmatter и даје могућност да се и мета-тагови задају у формату читљивом људима. Тако овај чланак почиње на следећи начин:

---
title: Нови почетак ✨
date: 2019-10-26T0:00:00.000Z
categories:
  - опште
  - ажурирања сајта
tags:
  - Nuxt.js
  - Markdown
---

Engine који развијам даље организује чланке на основу ових ознака.


  1. Jедноструких звездица, али нећемо ситничарити. ↩︎