Markdown with supress <p>
This commit is contained in:
parent
b0c7b6a690
commit
2ba61f10ff
@ -2,10 +2,12 @@ package aboutme
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"personalwebsite/apps/appCtx"
|
"personalwebsite/apps/appCtx"
|
||||||
"personalwebsite/errormessage"
|
"personalwebsite/errormessage"
|
||||||
|
"personalwebsite/libs"
|
||||||
"personalwebsite/webfilesystem"
|
"personalwebsite/webfilesystem"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -15,6 +17,7 @@ import (
|
|||||||
type AboutMeApp struct {
|
type AboutMeApp struct {
|
||||||
fs *webfilesystem.WebFileSystem
|
fs *webfilesystem.WebFileSystem
|
||||||
appID string
|
appID string
|
||||||
|
mLib libs.MarkdownLib
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAboutMeApp(webFs *webfilesystem.WebFileSystem) *AboutMeApp {
|
func NewAboutMeApp(webFs *webfilesystem.WebFileSystem) *AboutMeApp {
|
||||||
@ -54,12 +57,35 @@ func (p *AboutMeApp) PublicRoutes(route *gin.RouterGroup) {
|
|||||||
|
|
||||||
func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
||||||
p.PublicRoutes(router)
|
p.PublicRoutes(router)
|
||||||
router.GET("writeMock", func(ctx *gin.Context) {
|
// router.GET("writeMock", func(ctx *gin.Context) {
|
||||||
err := p.WriteMock()
|
// err := p.WriteMock()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
ctx.Status(http.StatusInternalServerError)
|
// ctx.Status(http.StatusInternalServerError)
|
||||||
}
|
// }
|
||||||
ctx.Status(http.StatusOK)
|
// ctx.Status(http.StatusOK)
|
||||||
|
// })
|
||||||
|
|
||||||
|
router.GET("getMock", func(ctx *gin.Context) {
|
||||||
|
ctx.JSON(http.StatusOK, PropertiesFileData{
|
||||||
|
Header: HeaderIsland{},
|
||||||
|
Islands: []Island{
|
||||||
|
{
|
||||||
|
Header: "qq",
|
||||||
|
Properties: []IslandProperty{
|
||||||
|
{
|
||||||
|
Key: "22",
|
||||||
|
KeyComments: []string{
|
||||||
|
"45",
|
||||||
|
"12",
|
||||||
|
},
|
||||||
|
Values: []string{
|
||||||
|
"aaaa",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
router.GET("read", func(ctx *gin.Context) {
|
router.GET("read", func(ctx *gin.Context) {
|
||||||
@ -93,7 +119,9 @@ func (p *AboutMeApp) PrivateRoutes(router *gin.RouterGroup) {
|
|||||||
propsData := PropertiesFileData{}
|
propsData := PropertiesFileData{}
|
||||||
err := ctx.BindJSON(&propsData)
|
err := ctx.BindJSON(&propsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Status(http.StatusBadRequest)
|
ctx.JSON(http.StatusBadRequest, errormessage.ErrorMessage{
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,72 +141,72 @@ func (p *AboutMeApp) GetAppID() string {
|
|||||||
return p.appID
|
return p.appID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AboutMeApp) WriteMock() error {
|
// func (p *AboutMeApp) WriteMock() error {
|
||||||
fileHeader := webfilesystem.FileHeader{
|
// fileHeader := webfilesystem.FileHeader{
|
||||||
MongoId: primitive.NewObjectID(),
|
// MongoId: primitive.NewObjectID(),
|
||||||
Name: "aboutme.props",
|
// Name: "aboutme.props",
|
||||||
Type: "personal-properties",
|
// Type: "personal-properties",
|
||||||
Icon: "",
|
// Icon: "",
|
||||||
}
|
// }
|
||||||
fileData := PropertiesFileData{
|
// fileData := PropertiesFileData{
|
||||||
Header: HeaderIsland{
|
// Header: HeaderIsland{
|
||||||
Name: "Test Name",
|
// Name: "Test Name",
|
||||||
IconPath: "test icon path",
|
// IconPath: "test icon path",
|
||||||
Info1: "Info1",
|
// Info1: "Info1",
|
||||||
Info2: "Info2",
|
// Info2: "Info2",
|
||||||
},
|
// },
|
||||||
Props: []PropIsland{
|
// Props: []PropIsland{
|
||||||
{
|
// {
|
||||||
Header: "Test Prop Header",
|
// Header: "Test Prop Header",
|
||||||
Props: []PropElement{
|
// Props: []PropElement{
|
||||||
{
|
// {
|
||||||
Key: "Test key",
|
// Key: "Test key",
|
||||||
KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
// KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
||||||
Values: []Value{
|
// Values: []Value{
|
||||||
{
|
// {
|
||||||
Blocks: []Block{
|
// Blocks: []ValueBlock{
|
||||||
{
|
// {
|
||||||
Type: "string",
|
// Type: "string",
|
||||||
Data: []string{"aappo"},
|
// Data: []string{"aappo"},
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
Type: "link",
|
// Type: "link",
|
||||||
Data: []string{"https://ya.ru", "Azazaza"},
|
// Data: []string{"https://ya.ru", "Azazaza"},
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
Header: "Test Prop Header 2",
|
// Header: "Test Prop Header 2",
|
||||||
Props: []PropElement{
|
// Props: []PropElement{
|
||||||
{
|
// {
|
||||||
Key: "Test key",
|
// Key: "Test key",
|
||||||
KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
// KeyComments: []string{"Test key comment 1", "Test key comment 1"},
|
||||||
Values: []Value{
|
// Values: []Value{
|
||||||
{
|
// {
|
||||||
Blocks: []Block{
|
// Blocks: []ValueBlock{
|
||||||
{
|
// {
|
||||||
Type: "string",
|
// Type: "string",
|
||||||
Data: []string{"aappo"},
|
// Data: []string{"aappo"},
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
Type: "link",
|
// Type: "link",
|
||||||
Data: []string{"https://ya.ru", "Azazaza"},
|
// Data: []string{"https://ya.ru", "Azazaza"},
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
_, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
// _, _, err := p.fs.Write("/Applications/AboutMe.app/aboutme.props", &fileHeader, fileData)
|
||||||
return err
|
// return err
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (p *AboutMeApp) Read(filePath string) (*PropertiesFileData, error) {
|
func (p *AboutMeApp) Read(filePath string) (*PropertiesFileData, error) {
|
||||||
propData := PropertiesFileData{}
|
propData := PropertiesFileData{}
|
||||||
@ -215,47 +243,84 @@ func (p *AboutMeApp) Edit(filePath string, blogData PropertiesFileData) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *AboutMeApp) Render(appCtx appCtx.AppContext, filePath string) (gin.H, error) {
|
func (p *AboutMeApp) Render(appCtx appCtx.AppContext, filePath string) (gin.H, error) {
|
||||||
propsData := PropertiesFileData{}
|
//Read file from WebFS
|
||||||
|
propsData := &PropertiesFileData{}
|
||||||
filePath = p.fs.RelativeToAbsolute(appCtx, filePath)
|
filePath = p.fs.RelativeToAbsolute(appCtx, filePath)
|
||||||
_, err := p.fs.Read(filePath, &propsData)
|
_, err := p.fs.Read(filePath, &propsData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Render Markdown strings
|
||||||
|
renderedIslands := []RenderedIsland{}
|
||||||
|
for _, island := range propsData.Islands {
|
||||||
|
newRenderedIsland := RenderedIsland{
|
||||||
|
Header: island.Header,
|
||||||
|
Properties: []RenderedIslandProperty{},
|
||||||
|
}
|
||||||
|
for _, property := range island.Properties {
|
||||||
|
newRenderedIslandProperty := RenderedIslandProperty{
|
||||||
|
Key: property.Key,
|
||||||
|
KeyComments: property.KeyComments,
|
||||||
|
Values: []template.HTML{},
|
||||||
|
}
|
||||||
|
for _, value := range property.Values {
|
||||||
|
renderedValue := p.mLib.Render([]byte(value), true)
|
||||||
|
newRenderedIslandProperty.Values = append(newRenderedIslandProperty.Values, renderedValue)
|
||||||
|
}
|
||||||
|
newRenderedIsland.Properties = append(newRenderedIsland.Properties, newRenderedIslandProperty)
|
||||||
|
}
|
||||||
|
renderedIslands = append(renderedIslands, newRenderedIsland)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Make icon path absolute
|
||||||
propsData.Header.IconPath = p.fs.RelativeToAbsolute(appCtx, propsData.Header.IconPath)
|
propsData.Header.IconPath = p.fs.RelativeToAbsolute(appCtx, propsData.Header.IconPath)
|
||||||
|
|
||||||
return gin.H{
|
return gin.H{
|
||||||
"headerProps": propsData.Header,
|
"HeaderProps": propsData.Header,
|
||||||
"allprops": propsData.Props,
|
"Islands": renderedIslands,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PropertiesFileData struct {
|
||||||
|
Header HeaderIsland `bson:"header"`
|
||||||
|
Islands []Island `bson:"islands"` //TODO rename
|
||||||
|
}
|
||||||
|
|
||||||
type HeaderIsland struct {
|
type HeaderIsland struct {
|
||||||
Name string `bson:"name"`
|
Name string `bson:"name"`
|
||||||
IconPath string `bson:"iconpath"`
|
IconPath string `bson:"iconpath"`
|
||||||
Info1 string `bson:"info1"`
|
Value1 string `bson:"value1"` //TODO Rename to value
|
||||||
Info2 string `bson:"info2"`
|
Value2 string `bson:"value2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PropElement struct {
|
type Island struct {
|
||||||
|
Header string `bson:"header"`
|
||||||
|
Properties []IslandProperty `bson:"properties"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IslandProperty struct {
|
||||||
|
Key string `bson:"key"`
|
||||||
|
KeyComments []string `bson:"keycomment"`
|
||||||
|
Values []string `bson:"values"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderedIsland struct {
|
||||||
|
Header string
|
||||||
|
Properties []RenderedIslandProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenderedIslandProperty struct {
|
||||||
Key string
|
Key string
|
||||||
KeyComments []string
|
KeyComments []string
|
||||||
Values []Value
|
Values []template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
type Value struct {
|
// type Value struct {
|
||||||
Blocks []Block
|
// Blocks []ValueBlock
|
||||||
}
|
// }
|
||||||
|
|
||||||
type Block struct {
|
// type ValueBlock struct {
|
||||||
Type string
|
// Type string
|
||||||
Data []string
|
// Data string
|
||||||
}
|
// }
|
||||||
|
|
||||||
type PropIsland struct {
|
|
||||||
Header string
|
|
||||||
Props []PropElement
|
|
||||||
}
|
|
||||||
|
|
||||||
type PropertiesFileData struct {
|
|
||||||
Header HeaderIsland `bson:"header"`
|
|
||||||
Props []PropIsland `bson:"props"`
|
|
||||||
}
|
|
||||||
|
@ -45,7 +45,7 @@ func (b *BlogViewerApplication) PrivateRoutes(route *gin.RouterGroup) {
|
|||||||
for _, block := range blogData.Blocks {
|
for _, block := range blogData.Blocks {
|
||||||
for _, str := range block.Data {
|
for _, str := range block.Data {
|
||||||
test := []byte(str)
|
test := []byte(str)
|
||||||
mLib.Render(test)
|
mLib.Render(test, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -239,7 +239,7 @@ func (b *BlogViewerApplication) Render(filePath string, appCtx appCtx.AppContext
|
|||||||
// }
|
// }
|
||||||
case "markdown":
|
case "markdown":
|
||||||
for _, data := range block.Data {
|
for _, data := range block.Data {
|
||||||
renderedMD := b.mLib.Render([]byte(data))
|
renderedMD := b.mLib.Render([]byte(data), true)
|
||||||
newBlock.Data = append(newBlock.Data, renderedMD)
|
newBlock.Data = append(newBlock.Data, renderedMD)
|
||||||
}
|
}
|
||||||
newData = append(newData, newBlock)
|
newData = append(newData, newBlock)
|
||||||
|
@ -2,6 +2,7 @@ package libs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/microcosm-cc/bluemonday"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
"github.com/russross/blackfriday/v2"
|
"github.com/russross/blackfriday/v2"
|
||||||
@ -10,8 +11,12 @@ import (
|
|||||||
type MarkdownLib struct {
|
type MarkdownLib struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ml *MarkdownLib) Render(s []byte) template.HTML {
|
func (ml *MarkdownLib) Render(md []byte, supressParagraph bool) template.HTML {
|
||||||
output := blackfriday.Run(s)
|
output := blackfriday.Run(md)
|
||||||
|
if supressParagraph {
|
||||||
|
output = []byte(strings.ReplaceAll(string(output), "<p>", ""))
|
||||||
|
output = []byte(strings.ReplaceAll(string(output), "</p>", ""))
|
||||||
|
}
|
||||||
_ = output
|
_ = output
|
||||||
html := bluemonday.UGCPolicy().SanitizeBytes(output)
|
html := bluemonday.UGCPolicy().SanitizeBytes(output)
|
||||||
// println(string(html))
|
// println(string(html))
|
||||||
|
@ -42,17 +42,17 @@ func PrivateRoutes(port string, webfs *webfilesystem.WebFileSystem, webde *wde.W
|
|||||||
Args: []string{"/home/user/Blogs/blog1.blog"},
|
Args: []string{"/home/user/Blogs/blog1.blog"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// aboutMe := AppString{
|
aboutMe := AppString{
|
||||||
// AppPath: "/Applications/AboutMe.app",
|
AppPath: "/Applications/AboutMe.app",
|
||||||
// Args: []string{},
|
Args: []string{},
|
||||||
// }
|
}
|
||||||
|
|
||||||
// appString2 := AppString{
|
// appString2 := AppString{
|
||||||
// AppPath: "/Applications/Finder.app",
|
// AppPath: "/Applications/Finder.app",
|
||||||
// Args: []string{"/home/user/", "--desktop", "desktop-layer"},
|
// Args: []string{"/home/user/", "--desktop", "desktop-layer"},
|
||||||
// }
|
// }
|
||||||
|
|
||||||
autostart := []AppString{appString}
|
autostart := []AppString{appString, aboutMe}
|
||||||
ctx.HTML(http.StatusOK, "index.tmpl", gin.H{
|
ctx.HTML(http.StatusOK, "index.tmpl", gin.H{
|
||||||
"autostart": autostart,
|
"autostart": autostart,
|
||||||
})
|
})
|
||||||
|
@ -12,44 +12,31 @@
|
|||||||
<div class="PropsView">
|
<div class="PropsView">
|
||||||
<div class="PropertiesList">
|
<div class="PropertiesList">
|
||||||
<div class="ShortBio">
|
<div class="ShortBio">
|
||||||
<img class="Image" src="/system/libs/img/get?path={{ .headerProps.IconPath }}" alt="My Photo">
|
<img class="Image" src="/system/libs/img/get?path={{ .HeaderProps.IconPath }}" alt="My Photo">
|
||||||
<div class="Text">
|
<div class="Text">
|
||||||
<div class="Name">{{ .headerProps.Name }}</div>
|
<div class="Name">{{ .HeaderProps.Name }}</div>
|
||||||
<div>{{ .headerProps.Info1 }}</div>
|
<div>{{ .HeaderProps.Value1 }}</div>
|
||||||
<div>{{ .headerProps.Info2 }}</div>
|
<div>{{ .HeaderProps.Value2 }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{ range $propIsland := .allprops }}
|
{{ range $island := .Islands }}
|
||||||
<!-- FIXME -->
|
<!-- FIXME -->
|
||||||
<div class="Island">
|
|
||||||
<div class="Title">
|
<div class="Island">
|
||||||
{{$propIsland.Header}}:
|
<div class="Title"> {{$island.Header}}:</div>
|
||||||
</div>
|
|
||||||
<div class="Content">
|
<div class="Content">
|
||||||
{{range $prop := $propIsland.Props}}
|
|
||||||
|
{{range $property := $island.Properties}}
|
||||||
<div class="Row">
|
<div class="Row">
|
||||||
<div class="Key">
|
<div class="Key">
|
||||||
{{$prop.Key}}:
|
{{$property.Key}}:
|
||||||
{{ range $keyComment := $prop.KeyComments }}
|
{{ range $keyComment := $property.KeyComments }}
|
||||||
<div class="KeyComment">
|
<div class="KeyComment">{{ $keyComment }}</div>
|
||||||
{{ $keyComment }}
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
<div class="Values">
|
<div class="Values">
|
||||||
{{ range $value := $prop.Values }}
|
{{ range $value := $property.Values }}
|
||||||
<div class="Value">
|
<div class="Value">{{ $value }}</div>
|
||||||
{{ range $block := $value.Blocks }}
|
|
||||||
{{ if eq $block.Type "link"}}
|
|
||||||
<a href="{{ index $block.Data 0}}">{{ index $block.Data 1}}</a>
|
|
||||||
{{ end }}
|
|
||||||
{{ if eq $block.Type "string"}}
|
|
||||||
{{ range $string := $block.Data}}
|
|
||||||
{{ $string }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
{{ end }}
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user