ssb-pubmd 0.1.1__tar.gz → 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/PKG-INFO +1 -1
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/pyproject.toml +3 -1
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/adapters/publish_client.py +5 -12
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/cli.py +38 -14
- ssb_pubmd-0.1.2/ssb_pubmd/config.py +37 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/notebook_client.py +4 -1
- ssb_pubmd-0.1.2/ssb_pubmd/templates/__init__.py +0 -0
- ssb_pubmd-0.1.2/ssb_pubmd/templates/template.qmd +138 -0
- ssb_pubmd-0.1.1/ssb_pubmd/config.py +0 -23
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/LICENSE +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/README.md +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/__init__.py +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/__main__.py +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/adapters/content_parser.py +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/adapters/document_processor.py +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/adapters/storage.py +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/domain/document_publisher.py +0 -0
- {ssb_pubmd-0.1.1 → ssb_pubmd-0.1.2}/ssb_pubmd/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "ssb-pubmd"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "SSB Pubmd"
|
|
5
5
|
authors = ["Olav Landsverk <stud-oll@ssb.no>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -9,6 +9,8 @@ homepage = "https://github.com/statisticsnorway/ssb-pubmd"
|
|
|
9
9
|
repository = "https://github.com/statisticsnorway/ssb-pubmd"
|
|
10
10
|
documentation = "https://statisticsnorway.github.io/ssb-pubmd"
|
|
11
11
|
classifiers = ["Development Status :: 3 - Alpha"]
|
|
12
|
+
include = ["ssb_pubmd/templates"]
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
[tool.poetry.urls]
|
|
14
16
|
Changelog = "https://github.com/statisticsnorway/ssb-pubmd/releases"
|
|
@@ -44,13 +44,8 @@ class LocalTokenClient:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
class DaplaTokenClient:
|
|
47
|
-
token: str
|
|
48
|
-
|
|
49
|
-
def __init__(self) -> None:
|
|
50
|
-
self.token = AuthClient.fetch_personal_token(audiences=["ssbno"])
|
|
51
|
-
|
|
52
47
|
def get_token(self) -> str:
|
|
53
|
-
return
|
|
48
|
+
return AuthClient.fetch_personal_token(audiences=["ssbno"])
|
|
54
49
|
|
|
55
50
|
class Response(NamedTuple):
|
|
56
51
|
publish_path: str
|
|
@@ -111,14 +106,12 @@ class MimirPublishClient:
|
|
|
111
106
|
)
|
|
112
107
|
|
|
113
108
|
|
|
114
|
-
def get_publish_client(
|
|
115
|
-
config: Config, use_dapla_token_client: bool = False
|
|
116
|
-
) -> PublishClient:
|
|
109
|
+
def get_publish_client(config: Config) -> PublishClient:
|
|
117
110
|
return MimirPublishClient(
|
|
118
111
|
base_url=config.publish_base_url,
|
|
119
|
-
endpoint=
|
|
120
|
-
preview_base_path=config.
|
|
112
|
+
endpoint="/webapp/pubmd",
|
|
113
|
+
preview_base_path=config.publish_admin_path + "/site/preview/default/draft",
|
|
121
114
|
token_client=DaplaTokenClient()
|
|
122
|
-
if use_dapla_token_client
|
|
115
|
+
if config.use_dapla_token_client
|
|
123
116
|
else DEFULT_TOKEN_CLIENT,
|
|
124
117
|
)
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
import sys
|
|
3
|
+
from importlib import resources
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
6
|
+
from jinja2 import Template
|
|
5
7
|
from watchfiles import watch
|
|
6
8
|
|
|
9
|
+
from ssb_pubmd import templates
|
|
7
10
|
from ssb_pubmd.adapters.content_parser import MimirContentParser
|
|
8
11
|
from ssb_pubmd.adapters.document_processor import PandocDocumentProcessor
|
|
9
12
|
from ssb_pubmd.adapters.publish_client import PublishClient
|
|
@@ -15,37 +18,58 @@ from ssb_pubmd.domain.document_publisher import sync_document
|
|
|
15
18
|
|
|
16
19
|
def run_cli(system_arguments: list[str], config: Config) -> None:
|
|
17
20
|
match system_arguments:
|
|
18
|
-
case [_, "
|
|
19
|
-
|
|
21
|
+
case [_, "create", filename]:
|
|
22
|
+
_create_template(filename, config)
|
|
23
|
+
case [_, "preview", filename]:
|
|
24
|
+
_preview(filename, config)
|
|
20
25
|
case _:
|
|
21
|
-
print("Usage:
|
|
26
|
+
print("Usage:")
|
|
27
|
+
print(" ssb-pubmd create FILENAME")
|
|
28
|
+
print(" ssb-pubmd preview FILENAME")
|
|
22
29
|
sys.exit(1)
|
|
23
30
|
|
|
24
31
|
|
|
32
|
+
def _create_template(filename: str, config: Config) -> None:
|
|
33
|
+
destination = Path.cwd() / filename
|
|
34
|
+
if destination.suffix != ".qmd":
|
|
35
|
+
print("The destination file path must have the '.qmd' extension.")
|
|
36
|
+
sys.exit(1)
|
|
37
|
+
|
|
38
|
+
with resources.open_text(templates, "template.qmd") as file:
|
|
39
|
+
raw_template = file.read()
|
|
40
|
+
|
|
41
|
+
rendered_template = Template(raw_template).render(
|
|
42
|
+
filepath=destination,
|
|
43
|
+
cms_admin_url=config.publish_base_url + config.publish_admin_path,
|
|
44
|
+
project_folder=destination.parent.name,
|
|
45
|
+
filename=destination.name,
|
|
46
|
+
)
|
|
47
|
+
destination.write_text(rendered_template)
|
|
48
|
+
print(
|
|
49
|
+
f"Successfully created template file {destination}.\n",
|
|
50
|
+
"Open the file for further instructions.",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
25
54
|
def _preview(file_path: str, config: Config) -> None:
|
|
26
55
|
if Path(file_path).suffix != ".qmd":
|
|
27
56
|
print("Only Quarto Markdown (.qmd) files are supported.")
|
|
28
57
|
sys.exit(1)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
publish_client = get_publish_client(config, use_dapla_token_client=True)
|
|
32
|
-
except Exception:
|
|
33
|
-
print("Failed to fetch labid token; using environment variable...")
|
|
34
|
-
publish_client = get_publish_client(config, use_dapla_token_client=False)
|
|
58
|
+
|
|
59
|
+
publish_client = get_publish_client(config)
|
|
35
60
|
|
|
36
61
|
_sync_updated_file(file_path, publish_client)
|
|
37
62
|
|
|
38
63
|
print("Watching for file changes...")
|
|
39
64
|
for changes in watch(file_path):
|
|
65
|
+
print("Found changes:")
|
|
66
|
+
print(changes)
|
|
40
67
|
_sync_updated_file(file_path, publish_client)
|
|
41
68
|
|
|
42
69
|
def _sync_updated_file(file_path: str, publish_client: PublishClient) -> None:
|
|
43
70
|
print("Syncing updated document...")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
print(f"Content synced successfully. Preview URL: {preview_url}")
|
|
47
|
-
except Exception as e:
|
|
48
|
-
print(f"Error during sync: {e}")
|
|
71
|
+
preview_url = _sync_quarto_file(file_path, publish_client)
|
|
72
|
+
print(f"Content synced successfully. Preview URL: {preview_url}")
|
|
49
73
|
|
|
50
74
|
def _sync_quarto_file(file_path: str, publish_client: PublishClient) -> str:
|
|
51
75
|
pandoc_document = _quarto_to_pandoc(file_path)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""App configuration through environment variables."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Config:
|
|
10
|
+
publish_base_url: str
|
|
11
|
+
publish_admin_path: str
|
|
12
|
+
use_dapla_token_client: bool
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
_TEST_CONFIG = Config(
|
|
16
|
+
publish_base_url="https://i.test.ssb.no",
|
|
17
|
+
publish_admin_path="/xp/admin",
|
|
18
|
+
use_dapla_token_client=True,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
_LOCAL_CONFIG = Config(
|
|
22
|
+
publish_base_url="http://localhost:8080",
|
|
23
|
+
publish_admin_path="/admin",
|
|
24
|
+
use_dapla_token_client=False,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_config(metadata_file_path: Path | None = None) -> Config:
|
|
29
|
+
if os.environ.get("SSB_PUBMD_ENVIRONMENT") == "local":
|
|
30
|
+
config = _LOCAL_CONFIG
|
|
31
|
+
else:
|
|
32
|
+
config = _TEST_CONFIG
|
|
33
|
+
|
|
34
|
+
if os.environ.get("SSB_PUBMD_TOKEN_CLIENT") == "local":
|
|
35
|
+
config.use_dapla_token_client = False
|
|
36
|
+
|
|
37
|
+
return config
|
|
@@ -45,7 +45,10 @@ def configure_factbox(
|
|
|
45
45
|
)
|
|
46
46
|
_store_user_content(user_key=key, content=content)
|
|
47
47
|
|
|
48
|
-
md = _get_markdown_snippet(
|
|
48
|
+
md = _get_markdown_snippet(
|
|
49
|
+
key,
|
|
50
|
+
placeholder_text="Faktaboksens tekst skrives her med Markdown-syntaks.\n\n### Underoverskrift\n\nNy paragraf.",
|
|
51
|
+
)
|
|
49
52
|
print(md)
|
|
50
53
|
|
|
51
54
|
|
|
File without changes
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
ssb:
|
|
3
|
+
path: /utdanning/grunnskoler/statistikk/elevar-i-grunnskolen/artikler
|
|
4
|
+
title: "Hovedtittel for artikkelen"
|
|
5
|
+
authors:
|
|
6
|
+
- name: Fornavn Etternavn
|
|
7
|
+
email: ---@ssb.no
|
|
8
|
+
- name: Fornavn Etternavn
|
|
9
|
+
email: ---@ssb.no
|
|
10
|
+
ingress: |
|
|
11
|
+
Ingress for artikkelen,
|
|
12
|
+
som kan skrives over flere linjer.
|
|
13
|
+
---
|
|
14
|
+
Dette er en SSB-artikkel skrevet med Quarto Markdown.
|
|
15
|
+
|
|
16
|
+
Neste steg:
|
|
17
|
+
|
|
18
|
+
1. Sjekk at du er logget inn i CMS-et: {{ cms_admin_url }}/tool/com.enonic.app.contentstudio/main.
|
|
19
|
+
|
|
20
|
+
2. Det er gitt et eksempel på CMS-mappe i feltet `path` ovenfor. Endre denne til CMS-mappen du ønsker å opprette artikkelen i. Dette må være en mappe du har skrivetilgang til.
|
|
21
|
+
|
|
22
|
+
3. Kjør kommandoen `poetry run ssb-pubmd preview {{ filepath }}`.
|
|
23
|
+
|
|
24
|
+
* Dette vil opprette en draft-artikkel og printe URL'en til en forhåndsvisning av artikkelen.
|
|
25
|
+
* Kommandoen fungerer tilsvarende som `quarto preview`, det vil si at forhåndsvisningen holdes oppdatert etter hvert som du endrer og lagrer denne filen.****
|
|
26
|
+
* Du må oppdatere nettleservinduet for å se endringene.
|
|
27
|
+
|
|
28
|
+
4. Les seksjonene nedenfor for en kort introduksjon til skriving av SSB-artikler i Quarto Markdown.
|
|
29
|
+
|
|
30
|
+
## Artikkelmetadata
|
|
31
|
+
|
|
32
|
+
Metadata-blokken øverst viser all metadata som kan settes for en artikkel.
|
|
33
|
+
Dette er noe begrenset i testversjonen, men vil senere være komplett.
|
|
34
|
+
Merk at `path` og `title` er obligatoriske felt.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Markdown
|
|
38
|
+
|
|
39
|
+
Se [Quarto-referansen](https://quarto.org/docs/authoring/markdown-basics.html). Merk at:
|
|
40
|
+
|
|
41
|
+
* Hovedoverskrift (`#`) støttes ikke, og skal settes i metadatablokken.
|
|
42
|
+
|
|
43
|
+
## Kode
|
|
44
|
+
|
|
45
|
+
Se [Quarto-referansen](https://quarto.org/docs/computations/python.html). Merk at:
|
|
46
|
+
|
|
47
|
+
* Ingen kodeblokker eller output vil komme med i artikkelen.
|
|
48
|
+
* [Kode i teksten](https://quarto.org/docs/computations/inline-code.html) støttes. Koden vil evalueres og erstattes med tekst før artikkelen sendes til CMS'et.
|
|
49
|
+
* All kode må kunne kjøres fra topp til bunn.
|
|
50
|
+
|
|
51
|
+
## SSB-komponenter
|
|
52
|
+
|
|
53
|
+
I testversjonen tilbys et begrenset utvalg SSB-komponenter.
|
|
54
|
+
Komponentene opprettes med Python og settes inn med Markdown.
|
|
55
|
+
|
|
56
|
+
### Opprette komponenter
|
|
57
|
+
|
|
58
|
+
Importér Python-pakken:
|
|
59
|
+
|
|
60
|
+
```{python}
|
|
61
|
+
import ssb_pubmd as ssb
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Kodeblokkene nedenfor viser opprettelse av to komponenter; et highchart og en faktaboks:
|
|
65
|
+
```{python}
|
|
66
|
+
import pandas as pd
|
|
67
|
+
data = {
|
|
68
|
+
"År": [
|
|
69
|
+
2000, 2001, 2002, 2003, 2004,
|
|
70
|
+
2005, 2006, 2007, 2008, 2009,
|
|
71
|
+
2010, 2011, 2012, 2013, 2014,
|
|
72
|
+
2015, 2016, 2017, 2018, 2019
|
|
73
|
+
],
|
|
74
|
+
"Andel": [
|
|
75
|
+
4, 3.3, 4.7, 5.6, 7.2,
|
|
76
|
+
6.7, 7, 7.3, 7.6, 7.7,
|
|
77
|
+
7.7, 7.6, 8, 8.6, 9.4,
|
|
78
|
+
10, 10.3, 10.7, 11.3, 11.7
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
df = pd.DataFrame(data)
|
|
82
|
+
|
|
83
|
+
ssb.Highchart(
|
|
84
|
+
key="my-highchart",
|
|
85
|
+
title="Highchart title",
|
|
86
|
+
dataframe=df,
|
|
87
|
+
graph_type="line",
|
|
88
|
+
xlabel="my_xlabel",
|
|
89
|
+
ylabel="my_ylabel"
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```{python}
|
|
94
|
+
ssb.Factbox(
|
|
95
|
+
key = "my-factbox",
|
|
96
|
+
title = "Factbox title",
|
|
97
|
+
display_type = "default")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Dokumentasjon: (link kommer).
|
|
101
|
+
* For å se alle funksjonene som tilbys, skriv `ssb.` på en kodelinje og tast `Ctrl + Space` (VSCode) eller `Tab` (Jupyterlab).
|
|
102
|
+
* VSCode: Dokumentasjonen til funksjonen vises automatisk i en popup-boks når man hovrer over funksjonen.
|
|
103
|
+
|
|
104
|
+
### Sette inn komponenter
|
|
105
|
+
|
|
106
|
+
Når du kjører en av kodeblokkene ovenfor, vil det printes en Markdown-snippet som kan kopieres og limes inn på en ny linje:
|
|
107
|
+
|
|
108
|
+
::: { #my-highchart .ssb }
|
|
109
|
+
:::
|
|
110
|
+
|
|
111
|
+
Merk at faktabokser settes inn med innhold:
|
|
112
|
+
|
|
113
|
+
::: { #my-factbox .ssb }
|
|
114
|
+
|
|
115
|
+
Faktaboksens tekst skrives her med Markdown-syntaks.
|
|
116
|
+
|
|
117
|
+
### Underoverskrift
|
|
118
|
+
|
|
119
|
+
Ny paragraf.
|
|
120
|
+
|
|
121
|
+
:::
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## Synkronisering
|
|
125
|
+
|
|
126
|
+
Etter å ha synkronisert denne filen til CMS'et, vil du se en ekstra fil i Dapla-tjenesten:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
{{ project_folder }}/
|
|
130
|
+
├── {{ filename }}
|
|
131
|
+
├── .ssbno.json
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Metadatafilen `.ssbno.json` er automatisk generert og inneholder metadata for den tilhørende CMS-artikkelen. Merk at:
|
|
135
|
+
|
|
136
|
+
* Dersom `.ssbno.json` slettes, vil en ny CMS-artikkel opprettes ved neste synkronisering.
|
|
137
|
+
* Dersom man jobber med to separate SSB-artikler, skal disse ligge i hver sin mappe, slik at de har hver sin metadatafil.
|
|
138
|
+
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"""App configuration through environment variables."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
APP_NAME = "SSB_PUBMD"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class Config:
|
|
12
|
-
publish_base_url: str
|
|
13
|
-
publish_endpoint: str
|
|
14
|
-
publish_preview_base_path: str
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def get_config(metadata_file_path: Path | None = None) -> Config:
|
|
18
|
-
"""Get config from enviromnent variables."""
|
|
19
|
-
return Config(
|
|
20
|
-
publish_base_url=os.environ[f"{APP_NAME}_BASE_URL"],
|
|
21
|
-
publish_endpoint=os.environ[f"{APP_NAME}_ENDPOINT"],
|
|
22
|
-
publish_preview_base_path=os.environ[f"{APP_NAME}_PREVIEW_BASE_PATH"],
|
|
23
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|