Compare commits

..

6 commits

9 changed files with 55 additions and 253 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@
.bundle .bundle
*.docx *.docx
*.epub *.epub
/slides/autoslide.md
/images/*.circo.svg /images/*.circo.svg
/images/*.dot.svg /images/*.dot.svg
/images/*.ora.png /images/*.ora.png

View file

@ -1,6 +1,7 @@
// engine.js // engine.js
// You have to run `npm i @marp-team/marp-core` at first. // You have to run `npm i @marp-team/marp-core` at first.
const { Marp } = require('@marp-team/marp-core') const { Marp } = require('@marp-team/marp-core')
const highlightLines = require('markdown-it-highlight-lines')
module.exports = opts => { module.exports = opts => {
@ -10,11 +11,12 @@ module.exports = opts => {
opts.html = true opts.html = true
// console.log(opts) // console.log(opts)
const marp = new Marp(opts) const marp = new Marp(opts)
// Disable parsing fragmented list // Disable parsing fragmented list
marp.markdown.core.ruler.disable('marpit_fragment') marp.markdown.core.ruler.disable('marpit_fragment')
return marp // Enable code lines highlighting
// ref. https://github.com/marp-team/marp-vscode/issues/146
return marp.use(highlightLines)
} }

View file

@ -2,14 +2,15 @@
@import-theme 'default'; @import-theme 'default';
$primaryColor: #662d91; $primaryColor: #662d91;
$secondaryColor: #241c1c; $secondaryColor: #f60;
$tertiaryColor: #111111; $tertiaryColor: #241c1c;
$textColor: #111111; $textColor: #111111;
body { body {
--primary-color: $primaryColor; --primary-color: $primaryColor;
--secondary-color: $secondaryColor; --secondary-color: $secondaryColor;
--text-color: $tertiaryColor; --tertiary-color: $tertiaryColor;
--text-color: $textColor;
} }
section { section {
@ -18,6 +19,14 @@ section {
padding: 120px 80px 80px 80px; padding: 120px 80px 80px 80px;
} }
// https://github.com/marp-team/marp-vscode/issues/146
.highlighted-line {
background-color: #ff0;
display: block;
margin: 0 -16px;
padding: 0 16px;
}
section footer { section footer {
opacity: 0.75; opacity: 0.75;
color: $textColor; } color: $textColor; }
@ -179,6 +188,12 @@ bc-row > bc-column[bc-secondary] {
padding: 24px; padding: 24px;
} }
bc-row > bc-column[bc-tertiary] {
background-color: $tertiaryColor;
color: white;
padding: 24px;
}
bc-row > bc-column[bc-grey] { bc-row > bc-column[bc-grey] {
background-color: #eeeeee; background-color: #eeeeee;
padding: 24px; padding: 24px;
@ -194,6 +209,10 @@ bc-row > bc-column:first-of-type {
margin-left: 0px; margin-left: 0px;
} }
bc-row > bc-column p:only-child {
margin-bottom: 0px;
}
bc-row > bc-column > h1:first-child, bc-row > bc-column > h1:first-child,
bc-row > bc-column > h2:first-child, bc-row > bc-column > h2:first-child,
bc-row > bc-column > h3:first-child, bc-row > bc-column > h3:first-child,
@ -203,7 +222,7 @@ bc-row > bc-column > h6:first-child {
margin-top: 0; margin-top: 0;
} }
p img:first-child:last-child[alt*="center"] { p img:only-child[alt*="center"] {
display: block; display: block;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;

View file

@ -29,12 +29,12 @@ DOCS_PORT=5100
SLIDES_PORT=5200 SLIDES_PORT=5200
## Find .md slides ## Find .md slides
SLIDES_MDPP=$(shell find $(SLIDES_DIR) \( -name '*.mdpp' ! -name '_*' \)) SLIDES_MDPP=$(shell find -L $(SLIDES_DIR) -regextype sed \( -name '*.mdpp' ! -regex '.*/_.*' \))
SLIDES_MDPP_MD=$(patsubst $(SLIDES_DIR)/%.mdpp,$(CACHE_SLIDES_DIR)/%.mdpp.md,$(SLIDES_MDPP)) SLIDES_MDPP_MD=$(patsubst $(SLIDES_DIR)/%.mdpp,$(CACHE_SLIDES_DIR)/%.mdpp.md,$(SLIDES_MDPP))
SLIDES_MDPP_MD_PDF=$(patsubst $(CACHE_SLIDES_DIR)/%.mdpp.md,$(BUILD_SLIDES_DIR)/%.pdf,$(SLIDES_MDPP_MD)) SLIDES_MDPP_MD_PDF=$(patsubst $(CACHE_SLIDES_DIR)/%.mdpp.md,$(BUILD_SLIDES_DIR)/%.pdf,$(SLIDES_MDPP_MD))
SLIDES_MDPP_MD_PPTX=$(patsubst $(CACHE_SLIDES_DIR)/%.mdpp.md,$(BUILD_SLIDES_DIR)/%.pptx,$(SLIDES_MDPP_MD)) SLIDES_MDPP_MD_PPTX=$(patsubst $(CACHE_SLIDES_DIR)/%.mdpp.md,$(BUILD_SLIDES_DIR)/%.pptx,$(SLIDES_MDPP_MD))
SLIDES_MD=$(shell find $(SLIDES_DIR) \( -name '*.md' ! -name '_*' \)) $(SLIDES_MDPP_MD) SLIDES_MD=$(shell find -L $(SLIDES_DIR) -regextype sed \( -name '*.md' ! -regex '.*/_.*' \)) $(SLIDES_MDPP_MD)
SLIDES_MD_PDF=$(patsubst $(SLIDES_DIR)/%.md,$(BUILD_SLIDES_DIR)/%.pdf,$(SLIDES_MD)) SLIDES_MD_PDF=$(patsubst $(SLIDES_DIR)/%.md,$(BUILD_SLIDES_DIR)/%.pdf,$(SLIDES_MD))
SLIDES_MD_PPTX=$(patsubst $(SLIDES_DIR)/%.md,$(BUILD_SLIDES_DIR)/%.pptx,$(SLIDES_MD)) SLIDES_MD_PPTX=$(patsubst $(SLIDES_DIR)/%.md,$(BUILD_SLIDES_DIR)/%.pptx,$(SLIDES_MD))
@ -42,22 +42,22 @@ SLIDES_MD_ALL=$(SLIDES_MDPP_MD) $(SLIDES_MD) $(SLIDES_DIR)/autoslide.md
SLIDES_PDF_ALL=$(SLIDES_MDPP_MD_PDF) $(SLIDES_MD_PDF) $(BUILD_SLIDES_DIR)/autoslide.pdf SLIDES_PDF_ALL=$(SLIDES_MDPP_MD_PDF) $(SLIDES_MD_PDF) $(BUILD_SLIDES_DIR)/autoslide.pdf
SLIDES_PPTX_ALL=$(SLIDES_MDPP_MD_PPTX) $(SLIDES_MD_PPTX) $(BUILD_SLIDES_DIR)/autoslide.pptx SLIDES_PPTX_ALL=$(SLIDES_MDPP_MD_PPTX) $(SLIDES_MD_PPTX) $(BUILD_SLIDES_DIR)/autoslide.pptx
DOCS_MD=$(shell find $(DOCS_DIR) \( -name '*.md' ! -name '_*' \)) DOCS_MD=$(shell find -L $(DOCS_DIR) -regextype sed \( -name '*.md' ! -regex '.*/_.*' \))
## Find .uml graphs ## Find .uml graphs
DOCS_IMAGES_UML=$(shell find $(IMAGES_DIR) \( -name '*.uml' ! -name '_*' \)) DOCS_IMAGES_UML=$(shell find -L $(IMAGES_DIR) -regextype sed \( -name '*.uml' ! -regex '.*/_.*' \))
DOCS_IMAGES_UML_SVG=$(patsubst $(IMAGES_DIR)/%.uml,$(BUILD_IMAGES_DIR)/%.uml.svg,$(DOCS_IMAGES_UML)) DOCS_IMAGES_UML_SVG=$(patsubst $(IMAGES_DIR)/%.uml,$(BUILD_IMAGES_DIR)/%.uml.svg,$(DOCS_IMAGES_UML))
## Find .dot graphs ## Find .dot graphs
DOCS_IMAGES_DOT=$(shell find $(IMAGES_DIR) \( -name '*.dot' ! -name '_*' \)) DOCS_IMAGES_DOT=$(shell find -L $(IMAGES_DIR) -regextype sed \( -name '*.dot' ! -regex '.*/_.*' \))
DOCS_IMAGES_DOT_SVG=$(patsubst $(IMAGES_DIR)/%.dot,$(BUILD_IMAGES_DIR)/%.dot.svg,$(DOCS_IMAGES_DOT)) DOCS_IMAGES_DOT_SVG=$(patsubst $(IMAGES_DIR)/%.dot,$(BUILD_IMAGES_DIR)/%.dot.svg,$(DOCS_IMAGES_DOT))
## Find .circo graphs ## Find .circo graphs
DOCS_IMAGES_CIRCO=$(shell find $(IMAGES_DIR) \( -name '*.circo' ! -name '_*' \)) DOCS_IMAGES_CIRCO=$(shell find -L $(IMAGES_DIR) -regextype sed \( -name '*.circo' ! -regex '.*/_.*' \))
DOCS_IMAGES_CIRCO_SVG=$(patsubst $(IMAGES_DIR)/%.circo,$(BUILD_IMAGES_DIR)/%.circo.svg,$(DOCS_IMAGES_CIRCO)) DOCS_IMAGES_CIRCO_SVG=$(patsubst $(IMAGES_DIR)/%.circo,$(BUILD_IMAGES_DIR)/%.circo.svg,$(DOCS_IMAGES_CIRCO))
## Find .ora images ## Find .ora images
DOCS_IMAGES_ORA=$(shell find $(IMAGES_DIR) \( -name '*.ora' ! -name '_*' \)) DOCS_IMAGES_ORA=$(shell find -L $(IMAGES_DIR) -regextype sed \( -name '*.ora' ! -regex '.*/_.*' \))
DOCS_IMAGES_ORA_PNG=$(patsubst $(IMAGES_DIR)/%.ora,$(BUILD_IMAGES_DIR)/%.ora.png,$(DOCS_IMAGES_ORA)) DOCS_IMAGES_ORA_PNG=$(patsubst $(IMAGES_DIR)/%.ora,$(BUILD_IMAGES_DIR)/%.ora.png,$(DOCS_IMAGES_ORA))
## Merge all lists ## Merge all lists
@ -74,15 +74,11 @@ prepare: prepare-slides prepare-docs ## install prerequisites
prepare-slides: ## install prerequisites for PDF slides only prepare-slides: ## install prerequisites for PDF slides only
npm install npm install
npm rebuild node-sass
npx browserslist@latest --update-db npx browserslist@latest --update-db
prepare-docs: ## install prerequisites for static docs site only prepare-docs: ## install prerequisites for static docs site only
pipenv install pipenv install
# if [ "$(SYSTEM_INSTALL)" -eq 1 ]; then \
# pipenv install --deploy --system ; \
#else \
# pipenv install ; \
#fi
.PHONY: prepare prepare-slides prepare-docs .PHONY: prepare prepare-slides prepare-docs
@ -93,6 +89,9 @@ images: $(DOCS_IMAGES_SVG) $(DOCS_IMAGES_PNG) ## build images
@echo " dot: $(DOCS_IMAGES_DOT)" @echo " dot: $(DOCS_IMAGES_DOT)"
@echo " circo: $(DOCS_IMAGES_CIRCO)" @echo " circo: $(DOCS_IMAGES_CIRCO)"
@echo "Built: $(DOCS_IMAGES_SVG) $(DOCS_IMAGES_PNG)" @echo "Built: $(DOCS_IMAGES_SVG) $(DOCS_IMAGES_PNG)"
for dir in $$(find -L $(DOCS_DIR) -type d -regextype sed -regex '.*/[0-9][^/]*/images$$') $(DOCS_DIR)/images ; do \
rsync -av $$dir/ $(SLIDES_DIR)/images/ || exit 1 ; \
done
.PHONY: images .PHONY: images
@ -126,17 +125,19 @@ watch: ## run development server
autoslide: $(SLIDES_DIR)/autoslide.md | $(BUILD_SLIDES_DIR) autoslide: $(SLIDES_DIR)/autoslide.md | $(BUILD_SLIDES_DIR)
$(SLIDES_DIR)/autoslide.md: $(DOCS_MD) $(SLIDES_DIR)/autoslide.md: $(DOCS_MD)
find $(DOCS_DIR) -regextype sed -regex '.*/[0-9][^/]*\.md' -print0 \ find -L $(DOCS_DIR) -regextype sed \( -regex '.*/[0-9][^/]*\.md' ! -regex '.*/_.*' \) -print0 \
| sort -z |xargs -0 cat \ | sort -z |xargs -0 cat \
> $(SLIDES_DIR)/autoslide.md > $(SLIDES_DIR)/autoslide.md
watch-autoslide-internal: watch-autoslide-internal:
# FIXME: use watchexec instead
while inotifywait -q -e move -e modify -e create -e attrib -e delete -e moved_to -r $(DOCS_DIR) ; do \ while inotifywait -q -e move -e modify -e create -e attrib -e delete -e moved_to -r $(DOCS_DIR) ; do \
sleep 0.25 ; \ sleep 0.25 ; \
$(MAKE) autoslide ; \ $(MAKE) autoslide ; \
done done
watch-tocupdate-internal: watch-tocupdate-internal:
# FIXME: use watchexec instead
while inotifywait -q -e move -e modify -e create -e attrib -e delete -e moved_to -r $(DOCS_DIR) ; do \ while inotifywait -q -e move -e modify -e create -e attrib -e delete -e moved_to -r $(DOCS_DIR) ; do \
sleep 2 ; \ sleep 2 ; \
$(MAKE) images ; \ $(MAKE) images ; \
@ -148,6 +149,7 @@ watch-docs-internal:
watch-slides-internal: .marp/theme.css watch-slides-internal: .marp/theme.css
PORT=$(SLIDES_PORT) \ PORT=$(SLIDES_PORT) \
npx marp \ npx marp \
--allow-local-files \
--engine $$(pwd)/.marp/engine.js \ --engine $$(pwd)/.marp/engine.js \
--html \ --html \
--theme $$(pwd)/.marp/theme.css \ --theme $$(pwd)/.marp/theme.css \
@ -229,7 +231,7 @@ build-docs-pdf: ## build pdf docs only
pipenv run mkdocs build \ pipenv run mkdocs build \
--site-dir $(BUILD_DOCS_DIR) --site-dir $(BUILD_DOCS_DIR)
pdftk \ pdftk \
$$(find $(BUILD_DOCS_DIR) -name *.pdf -not -name index.pdf |sort ) \ $$(find -L $(BUILD_DOCS_DIR) -name *.pdf -not -name index.pdf |sort ) \
cat output $(BUILD_DOCS_DIR)/docs.pdf cat output $(BUILD_DOCS_DIR)/docs.pdf
build-docs-html: ## build static docs site only build-docs-html: ## build static docs site only
@ -282,14 +284,14 @@ fixme:
docker-build: ## build docker image docker-build: ## build docker image
docker build \ docker build \
--file docker/Dockerfile \ --file docker/Dockerfile \
--tag glenux/teaching-boilerplate:$(BUILD_VERSION) \ --tag glenux/docmachine:$(BUILD_VERSION) \
. .
docker tag \ docker tag \
glenux/teaching-boilerplate:$(BUILD_VERSION) \ glenux/docmachine:$(BUILD_VERSION) \
glenux/teaching-boilerplate:latest glenux/docmachine:latest
docker-push: ## push docker image docker-push: ## push docker image
env docker push glenux/teaching-boilerplate:latest env docker push glenux/docmachine:latest
docker-pull: ## download docker image docker-pull: ## download docker image
env docker pull glenux/teaching-boilerplate:latest env docker pull glenux/docmachine:latest

View file

@ -20,4 +20,4 @@ pymdown-extensions = "*"
mkdocs-pdf-export-plugin = "*" mkdocs-pdf-export-plugin = "*"
[requires] [requires]
python_version = "3.9" python_version = "3.11"

View file

@ -1,5 +1,5 @@
FROM node:18-bullseye-slim FROM node:18-bookworm-slim
MAINTAINER Glenn ROLLAND <glenux@glenux.net> LABEL maintainer="Glenn ROLLAND glenux@glenux.net"
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y --no-install-recommends python3 python3-pip pipenv \ && apt-get install -y --no-install-recommends python3 python3-pip pipenv \

View file

@ -13,11 +13,10 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@marp-team/marp-cli": "^1.5.0", "@marp-team/marp-cli": "^1.5.0",
"@marp-team/marp-core": "^3.0.0",
"markdown-it-footnote": "^3.0.2",
"markdown-it-highlight-lines": "^1.0.2",
"foreman": "^3.0.1", "foreman": "^3.0.1",
"node-sass": "^7.0.0" "node-sass": "^7.0.0"
},
"devDependencies": {
"@marp-team/marp-core": "^3.0.0",
"markdown-it-footnote": "^3.0.2"
} }
} }

View file

@ -1,135 +0,0 @@
#!/bin/sh
# vim: set ft=sh:
# Set defaults
BASEDIR="$(pwd)"
BASEHASH="$(echo "$BASEDIR" |sha256sum |head -c7)"
ACTION="watch"
VERBOSITY="0"
DOCKER_IMAGE=glenux/docmachine:latest
DOCKER_OPT_TTY="-t"
gxt_usage() {
echo "Usage: $0 [options]"
echo ""
echo "-d, --data-dir DIR Content directory"
echo "-a, --action ACTION Action (watch, build, shell, etc.)"
echo "-t, --tty Enable TTY mode (needed for shell)"
echo "-v, --verbose Enable verbosity"
echo "-h, --help Show this help"
}
# Parse arguments
while [ $# -gt 0 ]; do
ARG="${1:-}"
OPT="${2:-}"
shift
# echo "DEBUG: ARG=$ARG OPT=$OPT"
case "$ARG" in
-a|--action)
shift # argument requires a parameter
if [ -z "$OPT" ]; then
>&2 echo "ERROR: missing argument for --action"
exit 1
fi
ACTION="$OPT"
;;
-d|--data-dir)
shift # argument requires a parameter
if [ -z "$OPT" ]; then
>&2 echo "ERROR: missing argument for --data-dir"
exit 1
fi
if [ ! -d "$OPT" ]; then
>&2 echo "ERROR: argument for --data-dir must be a directory"
exit 1
fi
BASEDIR="$(cd "$OPT" && pwd)"
;;
-h|--help)
>&2 gxt_usage
exit 0
;;
-T|--no-tty)
DOCKER_OPT_TTY=""
;;
-v|--verbosity)
VERBOSITY="$((VERBOSITY+1))"
;;
*)
>&2 gxt_usage
>&2 echo "ERROR: unknown option '$ARG'"
exit 1
;;
esac
done
echo "basedir = $BASEDIR"
echo "docker_image = $DOCKER_IMAGE"
echo "action = $ACTION"
## Detect Marp SCSS
if [ -f "$BASEDIR/.marp/theme.scss" ]; then
DOCKER_OPT_MARP_THEME="-v $BASEDIR/.marp:/app/.marp"
echo "Theme: detected Marp files. Adding option to command line ($DOCKER_OPT_MARP_THEME)"
else
echo "Theme: no theme detected. Using default files"
fi
## Detect Mkdocs configuration - old format (full)
if [ -f "$BASEDIR/mkdocs.yml" ]; then
>&2 echo "Mkdocs: detected mkdocs.yml file. Please rename to mkdocs-patch.yml"
exit 1
fi
## Detect Mkdocs configuration - new format (patch)
if [ -f "$BASEDIR/mkdocs-patch.yml" ]; then
DOCKER_OPT_MKDOCS_CONFIG="-v $BASEDIR/mkdocs-patch.yml:/app/mkdocs-patch.yml"
echo "Mkdocs: detected mkdocs-patch.yml file. Adding option to command line ($DOCKER_OPT_MKDOCS_CONFIG)"
else
echo "Mkdocs: no mkdocs-patch.yml detected. Using default files"
fi
## Detect slides
if [ -d "$BASEDIR/slides" ]; then
DOCKER_OPT_MARP_PORT="-p 5200:5200"
fi
## Detect docs
if [ -d "$BASEDIR/docs" ]; then
DOCKER_OPT_MKDOCS_PORT="-p 5100:5100"
fi
if [ "$VERBOSITY" -gt 0 ]; then
set -x
fi
DOCKER_NAME="docmachine-$BASEHASH"
DOCKER_CID="$(docker ps -f "name=$DOCKER_NAME" -q)"
if [ -n "$DOCKER_CID" ]; then
docker kill "$DOCKER_NAME"
fi
docker run -i $DOCKER_OPT_TTY \
--name "$DOCKER_NAME" \
--rm \
--shm-size=1gb \
-e "EXT_UID=$(id -u)" \
-e "EXT_GID=$(id -g)" \
-v "$BASEDIR/docs:/app/docs" \
-v "$BASEDIR/slides:/app/slides" \
-v "$BASEDIR/images:/app/images" \
-v "$BASEDIR/_build:/app/_build" \
$DOCKER_OPT_MKDOCS_CONFIG \
$DOCKER_OPT_MARP_THEME \
$DOCKER_OPT_MKDOCS_PORT \
$DOCKER_OPT_MARP_PORT \
"$DOCKER_IMAGE" "$ACTION"
if [ "$VERBOSITY" -gt 0 ]; then
set +x
fi

View file

@ -1,86 +0,0 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'fileutils'
require 'find'
require 'thor'
require 'colorize'
EXCLUDE_LIST = ['.git', 'node_modules'].freeze
SKEL_DIR = ENV['HOME'] + '/src/Glenux.Teaching/teaching-boilerplate'
if ! File.directory? SKEL_DIR
warn "ERROR: missing #{SKEL_DIR}"
exit 1
end
# TeachingCli
class TeachingCli < Thor
desc 'create PROJECT', 'Create PROJECT directory'
def create(target)
# Create dir
if target.empty?
warn 'Target not specified'
exit 1
end
puts "Creating project #{target}"
FileUtils.mkdir_p target
# Create structure
Find.find(SKEL_DIR) do |path|
if EXCLUDE_LIST.include? File.basename(path)
Find.prune
next
end
next unless File.directory?(path)
shortpath = path.gsub(SKEL_DIR, '').gsub(%r{^/}, '')
next if shortpath.empty?
targetpath = File.join(target, shortpath)
print "Creating directory #{shortpath}… "
FileUtils.mkdir_p targetpath
puts 'ok'.green
end
# Create files if possible
Find.find(SKEL_DIR) do |path|
if EXCLUDE_LIST.include? File.basename(path)
Find.prune
next
end
next if File.directory?(path)
shortpath = path.gsub(SKEL_DIR, '').gsub(%r{^/}, '')
next if shortpath.empty?
targetpath = File.join(target, shortpath)
print "Creating file #{shortpath}… "
# File does not exist => install it
unless File.exist? targetpath
FileUtils.cp path, targetpath
puts 'ok (installed)'.green
next
end
# File exist & different
unless system 'cmp', '--quiet', path, targetpath
if File.exist? targetpath + '.new'
puts 'error (pease solve previous conflict)'.red
else
puts 'warning (conflict when creating file)'.yellow
FileUtils.cp path, targetpath + '.new'
end
next
end
puts 'ok (identical)'.green
FileUtils.cp path, targetpath
end
end
end
TeachingCli.start(ARGV)