Gitmeyi Öğrenmeye Çalışmak – Ghost to Hugo 2

In: Genel



giriş

Tekrar hoşgeldiniz! Biz devam ediyor Dışa aktarılan Ghost veritabanını Markdown’a dönüştüren bir prototip program yapma yolculuğumuzda. Nihai hedef, elde edebileceğimiz shindakun.net Hugo ile çalışıyor ve çalışıyor. Geçen sefer, bunu oldukça kolaylaştırdık ve çoğunlukla dosyayı belleğe okumaya ve JSON’u bir Go yapısına dönüştürmeye odaklandık. Oradan ilk yazıyı yazdırdık.


Veri Gönder

Özetlemek gerekirse, burada posta alanlarından birinin içerdiği şey.

{
    "id": "60710b90705967038fe662d6",
    "uuid": "71ba3d71-ac18-4f33-82f7-1962baa83a07",
    "title": "db test",
    "slug": "db-test",
    "mobiledoc": "{"version":"0.3.1","markups":[],"atoms":[],"cards":[["markdown",{"cardName":"card-markdown","markdown":"\n<strike>This is a db test</strike>.\n"}]],"sections":[[10,0]],"ghostVersion":"3.0"}",
    "html": "<!--kg-card-begin: markdown--><p><strike>This is a db test</strike>.</p>n<!--kg-card-end: markdown-->",
    "comment_id": "2",
    "plaintext": "This is a db test.",
    "feature_image": null,
    "featured": 0,
    "type": "post",
    "status": "published",
    "locale": null,
    "visibility": "public",
    "email_recipient_filter": "none",
    "author_id": "60710b8d705967038fe66214",
    "created_at": "2004-08-09T19:11:20.000Z",
    "updated_at": "2004-08-09T19:11:20.000Z",
    "published_at": "2004-08-09T19:11:20.000Z",
    "custom_excerpt": null,
    "codeinjection_head": null,
    "codeinjection_foot": null,
    "custom_template": null,
    "canonical_url": null
},
Tam ekran moduna girinTam ekran modundan çık

Uygun ön maddeye sahip bir gönderi oluşturmak için ihtiyaç duyduğumuz alanların çoğu, geri aldığımız nesnenin içinde var. Başlık, bilgi, yayın tarihi vb. Görebiliriz. Markdown’ı içeren bölüm Mobiledoc olarak bilinen bir formattadır.


Mobil belge

Ghost belgelerine göre Mobiledoc

…Ghost ile yayınlamanın kalbini oluşturan standartlaştırılmış JSON tabanlı bir belge depolama formatı.

JSON nesnesinden ayıklanıp temizlendiğinde, üzerinde çalışabileceğimiz başka bir JSON parçasına sahip olacağız.

{
    "version": "0.3.1",
    "markups": [],
    "atoms": [],
    "cards": [
        [
            "markdown",
            {
                "cardName": "card-markdown",
                "markdown": "n<strike>This is a db test</strike>.n"
            }
        ]
    ],
    "sections": [
        [
            10,
            0
        ]
    ],
    "ghostVersion": "3.0"
}
Tam ekran moduna girinTam ekran modundan çık


Kulağa Kolay geliyor

İlk önce favori sitemizi kullanacağız, Gitmek için JSON JSON nesnesini birlikte çalışabileceğimiz bir yapıya dönüştürmek için dönüştürücü.

type Mobiledoc struct {
    Version string `json:"version"`
    Markups []interface{} `json:"markups"`
    Atoms []interface{} `json:"atoms"`
    Cards [][]interface{} `json:"cards"`
    Sections [][]int `json:"sections"`
    GhostVersion string `json:"ghostVersion"`
}
Tam ekran moduna girinTam ekran modundan çık

Kodumuz artık oldukça uzun, bu yüzden diğer yapıyı dışarıda bırakacağım GhostDatabase struct olsa da, aşağıdaki tam kod listesinde olacaktır. Hala kod çözme mantığımız üzerinde çalıştığımız için ekrana kod atıyor olacağız.

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "os"
    "strconv"
    "time"
)

type GhostDatabase struct {...}

type Mobiledoc struct {
    Version string `json:"version"`
    Markups []interface{} `json:"markups"`
    Atoms []interface{} `json:"atoms"`
    Cards [][]interface{} `json:"cards"`
    Sections [][]int `json:"sections"`
    GhostVersion string `json:"ghostVersion"`
}

func main() {
    fmt.Println("ghost2hugo")

    file, err := os.Open("shindakun-dot-net.ghost.2022-03-18-22-02-58.json")
    if err != nil {
        fmt.Println(err)
    }

    defer file.Close()

    b, err := io.ReadAll(file)
    if err != nil {
        fmt.Println(err)
    }

    var db GhostDatabase

    err = json.Unmarshal(b, &db)
    if err != nil {
        fmt.Println(err)
    }
Tam ekran moduna girinTam ekran modundan çık

Şimdilik ilk gönderiye odaklanmaya devam edelim, çünkü bu çalışmayı bir kez yaptıktan sonra, bu sadece “veritabanı” içinde bir döngü meselesi olmalı. Burası biraz zorlaştığı yer. Kullandığımız uygun bölüme inebilmek için birkaç iç içe diziyle çalışıyoruz. db.Db[0].Data.Posts[0].Mobiledoc. Bu, JSON nesnemizin çıkış sürümünün kullanılmasını sağlayacaktır.

"{"version":"0.3.1","markups":[],"atoms":[],"cards":[["markdown",{"cardName":"card-markdown","markdown":"\n<strike>This is a db test</strike>.\n"}]],"sections":[[10,0]],"ghostVersion":"3.0"}"

Tam ekran moduna girinTam ekran modundan çık


Bir Geziye Çıkalım

Kontrol ederek elde ettiğimiz ipten kurtulmanın bir yolu olacağını biliyordum. Belgelere git beni yönlendirdi strconv.Unquote.

Unquote, s’yi tek tırnaklı, çift tırnaklı veya geri alıntılı Go dize değişmezi olarak yorumlar ve tırnak içine alınan dize değerini döndürür. (s tek tırnaklıysa, bu bir Go karakteri değişmezi olur; Unquote karşılık gelen tek karakterli dizeyi döndürür.)

Tam ihtiyacımız olan şey! Bunun dışında, dizeden alıntıyı kaldırmaya çalıştığımda bir mesaj almaya devam ettim. invalid syntax hata. Bu biraz kafamı karıştırdı. Üzerinde kafa karıştırdıktan sonra, dizgenin başına bir geri tik ekler ve eklersem, bunun bir ham dizge değişmezi olarak ele alındığını fark ettim. Bu, aşağıdaki gibi görünen koda yol açar.

    c := "`" + db.Db[0].Data.Posts[0].Mobiledoc + "`"

    un, err := strconv.Unquote(c)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%vn", un)
Tam ekran moduna girinTam ekran modundan çık

Nihayet! JSON’umuz var!

{"version":"0.3.1","markups":[],"atoms":[],"cards":[["markdown",{"cardName":"card-markdown","markdown":"n<strike>This is a db test</strike>.n"}]],"sections":[[10,0]],"ghostVersion":"3.0"}
Tam ekran moduna girinTam ekran modundan çık

Şimdi, bunu daha önce kurduğumuz Mobiledoc yapısı içinde sıralayabiliriz!

    var md Mobiledoc

    err = json.Unmarshal([]byte(un), &md)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Printf("%#v", md)
Tam ekran moduna girinTam ekran modundan çık

Dökülen sonucumuzu kontrol ederek, beklenen verilere sahip olduğumuzu görebiliriz.

main.Mobiledoc{Version:"0.3.1", Markups:[]interface {}{}, Atoms:[]interface {}{}, Cards:[][]interface {}{[]interface {}{"markdown", map[string]interface {}{"cardName":"card-markdown", "markdown":"n<strike>This is a db test</strike>.n"}}}, Sections:[][]int{[]int{10, 0}}, GhostVersion:"3.0"}
Tam ekran moduna girinTam ekran modundan çık

Şu anda adı verilen bölümle ilgileniyoruz. Cards ki eğer saf bir şekilde erişmek istiyorsak aşağıdakileri kullanabiliriz.

    card := md.Cards[0][1]
    fmt.Printf("nncard: %#vn", card)
Tam ekran moduna girinTam ekran modundan çık
card: map[string]interface {}{"cardName":"card-markdown", "markdown":"n<strike>This is a db test</strike>.n"}
Tam ekran moduna girinTam ekran modundan çık

Bunu, erişimi biraz daha kolay bir şeye dönüştürelim.

    bbb := card.(map[string]interface{})
    fmt.Println(bbb["markdown"])
Tam ekran moduna girinTam ekran modundan çık
<strike>This is a db test</strike>.
Tam ekran moduna girinTam ekran modundan çık


Bir dahaki sefer

Şimdiye kadar çok iyi, Beklendiği gibi ilk gönderiden Markdown’ı çıkardık. Bir dahaki sefere, tüm gönderileri çıkarmaya çalışmak için küçük bir döngü yazacağız. İçimde eğlencenin başlayacağına dair bir his var.




Kod Listeleme

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "os"
    "strconv"
    "time"
)

type GhostDatabase struct {
    Db []struct {
        Meta struct {
            ExportedOn int64 `json:"exported_on"`
            Version string `json:"version"`
        } `json:"meta"`
        Data struct {
            Posts []struct {
                ID string `json:"id"`
                UUID string `json:"uuid"`
                Title string `json:"title"`
                Slug string `json:"slug"`
                Mobiledoc string `json:"mobiledoc"`
                HTML string `json:"html"`
                CommentID string `json:"comment_id"`
                Plaintext string `json:"plaintext"`
                FeatureImage interface{} `json:"feature_image"`
                Featured int `json:"featured"`
                Type string `json:"type"`
                Status string `json:"status"`
                Locale interface{} `json:"locale"`
                Visibility string `json:"visibility"`
                EmailRecipientFilter string `json:"email_recipient_filter"`
                AuthorID string `json:"author_id"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
                PublishedAt time.Time `json:"published_at"`
                CustomExcerpt interface{} `json:"custom_excerpt"`
                CodeinjectionHead interface{} `json:"codeinjection_head"`
                CodeinjectionFoot interface{} `json:"codeinjection_foot"`
                CustomTemplate interface{} `json:"custom_template"`
                CanonicalURL interface{} `json:"canonical_url"`
            } `json:"posts"`
            PostsAuthors []struct {
                ID string `json:"id"`
                PostID string `json:"post_id"`
                AuthorID string `json:"author_id"`
                SortOrder int `json:"sort_order"`
            } `json:"posts_authors"`
            PostsMeta []interface{} `json:"posts_meta"`
            PostsTags []struct {
                ID string `json:"id"`
                PostID string `json:"post_id"`
                TagID string `json:"tag_id"`
                SortOrder int `json:"sort_order"`
            } `json:"posts_tags"`
            Roles []struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Description string `json:"description"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"roles"`
            RolesUsers []struct {
                ID string `json:"id"`
                RoleID string `json:"role_id"`
                UserID string `json:"user_id"`
            } `json:"roles_users"`
            Settings []struct {
                ID string `json:"id"`
                Group string `json:"group"`
                Key string `json:"key"`
                Value string `json:"value"`
                Type string `json:"type"`
                Flags interface{} `json:"flags"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"settings"`
            Tags []struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Slug string `json:"slug"`
                Description interface{} `json:"description"`
                FeatureImage interface{} `json:"feature_image"`
                ParentID interface{} `json:"parent_id"`
                Visibility string `json:"visibility"`
                OgImage interface{} `json:"og_image"`
                OgTitle interface{} `json:"og_title"`
                OgDescription interface{} `json:"og_description"`
                TwitterImage interface{} `json:"twitter_image"`
                TwitterTitle interface{} `json:"twitter_title"`
                TwitterDescription interface{} `json:"twitter_description"`
                MetaTitle interface{} `json:"meta_title"`
                MetaDescription interface{} `json:"meta_description"`
                CodeinjectionHead interface{} `json:"codeinjection_head"`
                CodeinjectionFoot interface{} `json:"codeinjection_foot"`
                CanonicalURL interface{} `json:"canonical_url"`
                AccentColor interface{} `json:"accent_color"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"tags"`
            Users []struct {
                ID string `json:"id"`
                Name string `json:"name"`
                Slug string `json:"slug"`
                Password string `json:"password"`
                Email string `json:"email"`
                ProfileImage string `json:"profile_image"`
                CoverImage interface{} `json:"cover_image"`
                Bio interface{} `json:"bio"`
                Website interface{} `json:"website"`
                Location interface{} `json:"location"`
                Facebook interface{} `json:"facebook"`
                Twitter interface{} `json:"twitter"`
                Accessibility string `json:"accessibility"`
                Status string `json:"status"`
                Locale interface{} `json:"locale"`
                Visibility string `json:"visibility"`
                MetaTitle interface{} `json:"meta_title"`
                MetaDescription interface{} `json:"meta_description"`
                Tour interface{} `json:"tour"`
                LastSeen time.Time `json:"last_seen"`
                CreatedAt time.Time `json:"created_at"`
                UpdatedAt time.Time `json:"updated_at"`
            } `json:"users"`
        } `json:"data"`
    } `json:"db"`
}

type Mobiledoc struct {
    Version string `json:"version"`
    Markups []interface{} `json:"markups"`
    Atoms []interface{} `json:"atoms"`
    Cards [][]interface{} `json:"cards"`
    Sections [][]int `json:"sections"`
    GhostVersion string `json:"ghostVersion"`
}

func main() {
    fmt.Println("ghost2hugo")

    file, err := os.Open("shindakun-dot-net.ghost.2022-03-18-22-02-58.json")
    if err != nil {
        fmt.Println(err)
    }

    defer file.Close()

    b, err := io.ReadAll(file)
    if err != nil {
        fmt.Println(err)
    }

    var db GhostDatabase

    err = json.Unmarshal(b, &db)
    if err != nil {
        fmt.Println(err)
    }

    c := "`" + db.Db[0].Data.Posts[0].Mobiledoc + "`"

    un, err := strconv.Unquote(c)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%v", un)

    var md Mobiledoc

    err = json.Unmarshal([]byte(un), &md)
    if err != nil {
        fmt.Println(err)
    }

    fmt.Printf("%#v", md)

    card := md.Cards[0][1]
    fmt.Printf("nncard: %#vn", card)

    bbb := card.(map[string]interface{})
    fmt.Println(bbb["markdown"])
}
Tam ekran moduna girinTam ekran modundan çık

Bir cevap yazın

Ready to Grow Your Business?

We Serve our Clients’ Best Interests with the Best Marketing Solutions. Find out More

How Can We Help You?

Need to bounce off ideas for an upcoming project or digital campaign? Looking to transform your business with the implementation of full potential digital marketing?

For any career inquiries, please visit our careers page here.
[contact-form-7 404 "Bulunamadı"]