init wompum header image
This commit is contained in:
40
data/colors.yaml
Normal file
40
data/colors.yaml
Normal file
@ -0,0 +1,40 @@
|
||||
sand:
|
||||
100: "#eee8dd"
|
||||
500: "#d4c5aa"
|
||||
900: "#b19360"
|
||||
pink:
|
||||
100: "#ead4d2"
|
||||
500: "#c0928a"
|
||||
900: "#a7695a"
|
||||
red:
|
||||
100: "#e8c9c9"
|
||||
500: "#b87977"
|
||||
900: "#a35754"
|
||||
rust:
|
||||
100: "#eacec4"
|
||||
500: "#c48a74"
|
||||
900: "#af6649"
|
||||
clay:
|
||||
100: "#ead4c2"
|
||||
500: "#c49b6f"
|
||||
900: "#b17f48"
|
||||
gold:
|
||||
100: "#e6dac1"
|
||||
500: "#bca66d"
|
||||
900: "#a88b48"
|
||||
moss:
|
||||
100: "#d0ddc7"
|
||||
500: "#919f71"
|
||||
900: "#69734a"
|
||||
pine:
|
||||
100: "#c7ddd2"
|
||||
500: "#7b9b85"
|
||||
900: "#516b57"
|
||||
cyan:
|
||||
100: "#c0dadd"
|
||||
500: "#6a9799"
|
||||
900: "#436668"
|
||||
blue:
|
||||
100: "#c2cfe0"
|
||||
500: "#6f88a3"
|
||||
900: "#5d7691"
|
@ -6,6 +6,7 @@
|
||||
{{ .Title }}
|
||||
</title>
|
||||
<meta name="description" content="{{ .Description }}" />
|
||||
{{ partial "css-variables.html" . }}
|
||||
{{/* styles */}}
|
||||
{{ $options := dict "inlineImports" true }}
|
||||
{{ $styles := resources.Get "css/styles.css" }}
|
||||
@ -14,6 +15,7 @@
|
||||
{{ $styles = $styles | minify | fingerprint | resources.PostProcess }}
|
||||
{{ end }}
|
||||
<link href="{{ $styles.RelPermalink }}" rel="stylesheet" />
|
||||
<link href="/css/wompum.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body class="">
|
||||
{{ partial "header.html" . }}
|
||||
|
@ -1,17 +1,18 @@
|
||||
{{ define "main" }}
|
||||
<article class="flex flex-col lg:flex-row-reverse">
|
||||
<header class="lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:w-1/3 p-4">
|
||||
<h1 class="font-bold">{{ .Title }}</h1>
|
||||
<p><strong>Date:</strong> <time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "January 2, 2006" }}</time></p>
|
||||
<p><strong>Narrator:</strong> {{ .Params.narrator }}</p>
|
||||
<p><strong>Facilitator:</strong> {{ .Params.facilitator }}</p>
|
||||
<p><strong>Subject:</strong> {{ .Params.subject }}</p>
|
||||
<p><strong>Tags:</strong> {{ partial "tags.html" . }}</p>
|
||||
</header>
|
||||
<div class="prose lg:prose-xl lg:w-2/3 p-4">
|
||||
<p class="font-bold text-4xl">{{ .Title }}</p>
|
||||
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="flex flex-col lg:flex-row-reverse">
|
||||
<header class="lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:w-1/3 p-4">
|
||||
<h1 class="font-bold">{{ .Title }}</h1>
|
||||
<p><strong>Date:</strong> <time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "January 2, 2006" }}</time></p>
|
||||
<p><strong>Narrator:</strong> {{ .Params.narrator }}</p>
|
||||
<p><strong>Facilitator:</strong> {{ .Params.facilitator }}</p>
|
||||
<p><strong>Subject:</strong> {{ .Params.subject }}</p>
|
||||
<p><strong>Tags:</strong> {{ partial "tags.html" . }}</p>
|
||||
</header>
|
||||
<div class="prose lg:prose-xl lg:w-2/3 p-4">
|
||||
{{ partial "article-wompum.html" . }}
|
||||
<p class="font-bold text-4xl">{{ .Title }}</p>
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</article>
|
||||
{{ end }}
|
@ -5,6 +5,7 @@
|
||||
<ul class="flex flex-col gap-4 my-4">
|
||||
{{ range where .Site.RegularPages "Section" "oral-histories" }}
|
||||
<li class="border-l border-gray-300 pl-4">
|
||||
{{ partial "article-wompum.html" . }}
|
||||
<p class="text-xs text-gray-800"><time datetime="{{ .Date.Format " 2006-01-02" }}">{{ .Date.Format "January 2, 2006" }}</time></p>
|
||||
<a class="font-bold hover:text-green-900 underline" href="{{ .RelPermalink }}">{{ .Title }}</a>
|
||||
<p class="text-sm">{{ .Params.summary }}</p>
|
||||
|
12
layouts/partials/article-wompum.html
Normal file
12
layouts/partials/article-wompum.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div class="wompum-container">
|
||||
<div class="wompum-grid"
|
||||
data-metadata="{{ jsonify .Params }}"
|
||||
>
|
||||
<!-- Grid will be populated by JavaScript -->
|
||||
<!-- 7x5 = 35 cells total -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/sigil.js"></script>
|
||||
<script src="/js/colorCalculator.js"></script>
|
||||
<script src="/js/wompum.js"></script>
|
9
layouts/partials/css-variables.html
Normal file
9
layouts/partials/css-variables.html
Normal file
@ -0,0 +1,9 @@
|
||||
<style>
|
||||
:root {
|
||||
{{ range $colorName, $shades := site.Data.colors }}
|
||||
{{ range $shade, $value := $shades }}
|
||||
--{{ $colorName }}-{{ $shade }}: {{ $value }};
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
}
|
||||
</style>
|
25
layouts/partials/sigil.html
Normal file
25
layouts/partials/sigil.html
Normal file
@ -0,0 +1,25 @@
|
||||
{{/* Partial: create_sigil.html */}}
|
||||
|
||||
{{- $input := . -}} <!-- The input string will be passed into the partial -->
|
||||
{{- $vowels := "aeiouAEIOU" -}} <!-- List of vowels to remove -->
|
||||
{{- $seen := dict -}} <!-- Dictionary to track characters we've already encountered -->
|
||||
{{- $output := "" -}} <!-- Variable to store the resulting sigil -->
|
||||
{{- $chars := split (replaceRE "[^a-zA-Z]" "" $input) "" -}} <!-- Remove non-alphabetic characters and split the input string into a slice of characters -->
|
||||
|
||||
{{- /* Step 1: Remove vowels */ -}}
|
||||
{{- range $i, $char := $chars -}}
|
||||
{{- if not (in $vowels $char) -}}
|
||||
{{- /* Step 2: Remove repeating letters */ -}}
|
||||
{{- if not (index $seen $char) -}}
|
||||
{{- $seen = merge $seen (dict $char true) -}}
|
||||
{{- $output = printf "%s%s" $output $char -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $output = upper $output -}}
|
||||
{{ $output = split $output "" }}
|
||||
{{ $output = apply $output "printf" "%#x" "." }}
|
||||
{{ $output = apply $output "int" "." }}
|
||||
|
||||
{{- $output -}}<br>
|
30
static/css/wompum.css
Normal file
30
static/css/wompum.css
Normal file
@ -0,0 +1,30 @@
|
||||
.wompum-container {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.wompum-grid {
|
||||
display: grid;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wompum-cell {
|
||||
width: 100%;
|
||||
min-height: 30px; /* Minimum height for cells */
|
||||
background-color: var(--sand-500);
|
||||
}
|
||||
|
||||
/* Create pseudo-random pattern using prime numbers */
|
||||
.wompum-cell:nth-child(7n+1) {
|
||||
background-color: var(--sand-100);
|
||||
}
|
||||
|
||||
.wompum-cell:nth-child(5n+2) {
|
||||
background-color: var(--sand-900);
|
||||
}
|
||||
|
||||
.wompum-cell:nth-child(11n+3) {
|
||||
background-color: var(--sand-500);
|
||||
}
|
30
static/js/colorCalculator.js
Normal file
30
static/js/colorCalculator.js
Normal file
@ -0,0 +1,30 @@
|
||||
class ColorCalculator {
|
||||
constructor() {
|
||||
// Available color families from our palette
|
||||
this.colorFamilies = ['sand', 'pink', 'red', 'rust', 'clay', 'gold', 'moss', 'pine', 'cyan', 'blue'];
|
||||
// Available shades for each color
|
||||
this.shades = ['100', '500', '900'];
|
||||
}
|
||||
|
||||
// Get color based on sigil digit and influences
|
||||
getColor(sigilDigit, influences = []) {
|
||||
// Map digit 0-9 to color family
|
||||
const colorFamily = this.colorFamilies[sigilDigit];
|
||||
|
||||
// Calculate shade based on influences
|
||||
const shade = this.calculateShade(influences);
|
||||
|
||||
return `var(--${colorFamily}-${shade})`;
|
||||
}
|
||||
|
||||
// Calculate shade based on surrounding influences
|
||||
calculateShade(influences) {
|
||||
if (!influences.length) return '500';
|
||||
|
||||
// Average the influences and map to one of our three shades
|
||||
const avg = influences.reduce((sum, val) => sum + val, 0) / influences.length;
|
||||
if (avg < 3) return '100';
|
||||
if (avg > 6) return '900';
|
||||
return '500';
|
||||
}
|
||||
}
|
44
static/js/sigil.js
Normal file
44
static/js/sigil.js
Normal file
@ -0,0 +1,44 @@
|
||||
class Sigil {
|
||||
// Convert string to sigil array
|
||||
static generate(str) {
|
||||
if (!str) return [];
|
||||
|
||||
// Convert to lowercase, remove non-word characters
|
||||
const cleaned = str.toLowerCase().replace(/[^a-z]/g, '');
|
||||
|
||||
// Remove vowels
|
||||
const noVowels = cleaned.replace(/[aeiou]/g, '');
|
||||
|
||||
// Remove duplicate characters
|
||||
const deduped = [...new Set(noVowels)].join('');
|
||||
|
||||
// Convert to ASCII values and get digital roots
|
||||
return [...deduped].map(char => {
|
||||
const ascii = char.charCodeAt(0);
|
||||
return Sigil.getDigitalRoot(ascii);
|
||||
});
|
||||
}
|
||||
|
||||
// Get digital root of a number (sum digits until single digit)
|
||||
static getDigitalRoot(num) {
|
||||
if (num < 10) return num;
|
||||
return Sigil.getDigitalRoot([...num.toString()].reduce((sum, digit) => sum + parseInt(digit), 0));
|
||||
}
|
||||
|
||||
// Helper to validate and debug sigil generation
|
||||
static debug(str) {
|
||||
console.log({
|
||||
original: str,
|
||||
lowercase: str.toLowerCase(),
|
||||
cleaned: str.toLowerCase().replace(/[^a-z]/g, ''),
|
||||
noVowels: str.toLowerCase().replace(/[^a-z]/g, '').replace(/[aeiou]/g, ''),
|
||||
deduped: [...new Set(str.toLowerCase().replace(/[^a-z]/g, '').replace(/[aeiou]/g, ''))].join(''),
|
||||
sigil: Sigil.generate(str)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Export for use in other files
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = Sigil;
|
||||
}
|
149
static/js/wompum.js
Normal file
149
static/js/wompum.js
Normal file
@ -0,0 +1,149 @@
|
||||
class WompumGrid {
|
||||
constructor(element, metadata) {
|
||||
this.gridElement = element;
|
||||
this.metadata = metadata;
|
||||
this.gridSize = {
|
||||
columns: parseInt(element.dataset.columns) || 7,
|
||||
rows: parseInt(element.dataset.rows) || 5
|
||||
};
|
||||
|
||||
// Set grid template columns based on data attribute or default
|
||||
this.gridElement.style.gridTemplateColumns = `repeat(${this.gridSize.columns}, 1fr)`;
|
||||
|
||||
// Generate sigils for each metadata component
|
||||
this.sigils = {
|
||||
narrator: Sigil.generate(metadata.narrator),
|
||||
subject: Sigil.generate(metadata.subject),
|
||||
facilitator: Sigil.generate(metadata.facilitator)
|
||||
};
|
||||
|
||||
// Initialize color calculator
|
||||
this.colorCalculator = new ColorCalculator();
|
||||
|
||||
// Store sigils as data attributes for future use
|
||||
this.gridElement.dataset.narratorSigil = JSON.stringify(this.sigils.narrator);
|
||||
this.gridElement.dataset.subjectSigil = JSON.stringify(this.sigils.subject);
|
||||
this.gridElement.dataset.facilitatorSigil = JSON.stringify(this.sigils.facilitator);
|
||||
}
|
||||
|
||||
// Get sigil digit for a cell based on its section and position
|
||||
getSigilDigit(section, position) {
|
||||
const sigil = this.sigils[section];
|
||||
if (!sigil || !sigil.length) return 0;
|
||||
return sigil[position % sigil.length];
|
||||
}
|
||||
|
||||
// Get influences from adjacent cells
|
||||
getInfluences(column, row) {
|
||||
const influences = [];
|
||||
|
||||
// Check adjacent cells (up, down, left, right)
|
||||
const adjacentPositions = [
|
||||
[column, row - 1], // up
|
||||
[column, row + 1], // down
|
||||
[column - 1, row], // left
|
||||
[column + 1, row] // right
|
||||
];
|
||||
|
||||
for (const [adjCol, adjRow] of adjacentPositions) {
|
||||
if (adjCol >= 0 && adjCol < this.gridSize.columns &&
|
||||
adjRow >= 0 && adjRow < this.gridSize.rows) {
|
||||
const cell = this.gridElement.querySelector(
|
||||
`[data-column="${adjCol}"][data-row="${adjRow}"]`
|
||||
);
|
||||
if (cell && cell.dataset.sigilDigit) {
|
||||
influences.push(parseInt(cell.dataset.sigilDigit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return influences;
|
||||
}
|
||||
|
||||
// Apply metadata-based design to the grid
|
||||
applyMetadataDesign() {
|
||||
const cells = this.gridElement.querySelectorAll('.wompum-cell');
|
||||
|
||||
cells.forEach(cell => {
|
||||
const section = cell.dataset.section;
|
||||
const column = parseInt(cell.dataset.column);
|
||||
const row = parseInt(cell.dataset.row);
|
||||
|
||||
// Get sigil digit for this cell
|
||||
const sigilDigit = this.getSigilDigit(section, row);
|
||||
cell.dataset.sigilDigit = sigilDigit;
|
||||
|
||||
// Get influences from adjacent cells
|
||||
const influences = this.getInfluences(column, row);
|
||||
|
||||
// Calculate and apply color
|
||||
const color = this.colorCalculator.getColor(sigilDigit, influences);
|
||||
cell.style.backgroundColor = color;
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize the grid
|
||||
init() {
|
||||
if (!this.gridElement) return;
|
||||
this.createGrid();
|
||||
this.applyMetadataDesign();
|
||||
this.setGridAreas();
|
||||
}
|
||||
|
||||
// Define grid areas for each section
|
||||
setGridAreas() {
|
||||
const totalColumns = this.gridSize.columns;
|
||||
const narratorColumns = 2;
|
||||
const facilitatorColumns = 2;
|
||||
const subjectColumns = totalColumns - narratorColumns - facilitatorColumns;
|
||||
|
||||
this.gridElement.style.gridTemplateAreas = `
|
||||
"narrator subject facilitator"
|
||||
`;
|
||||
// this.gridElement.style.gridTemplateColumns = `${narratorColumns}fr ${subjectColumns}fr ${facilitatorColumns}fr`;
|
||||
}
|
||||
|
||||
// Create the grid cells with position awareness
|
||||
createGrid() {
|
||||
const totalCells = this.gridSize.columns * this.gridSize.rows;
|
||||
|
||||
for (let i = 0; i < totalCells; i++) {
|
||||
const cell = document.createElement('div');
|
||||
const column = i % this.gridSize.columns;
|
||||
const row = Math.floor(i / this.gridSize.columns);
|
||||
|
||||
// Determine which section this cell belongs to
|
||||
let section;
|
||||
if (column < 2) section = 'narrator';
|
||||
else if (column >= this.gridSize.columns - 2) section = 'facilitator';
|
||||
else section = 'subject';
|
||||
|
||||
cell.className = 'wompum-cell';
|
||||
cell.setAttribute('data-cell-index', i);
|
||||
cell.setAttribute('data-section', section);
|
||||
cell.setAttribute('data-column', column);
|
||||
cell.setAttribute('data-row', row);
|
||||
|
||||
this.gridElement.appendChild(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for DOM to be ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Find all grid elements
|
||||
const gridElements = document.querySelectorAll('.wompum-grid');
|
||||
|
||||
// Initialize a grid for each element found
|
||||
gridElements.forEach(element => {
|
||||
let metadata = {};
|
||||
try {
|
||||
metadata = JSON.parse(element.dataset.metadata || '{}');
|
||||
} catch (e) {
|
||||
console.error('Error parsing metadata for grid:', e);
|
||||
}
|
||||
|
||||
const wompum = new WompumGrid(element, metadata);
|
||||
wompum.init();
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user