190 lines
8.1 KiB
Python
190 lines
8.1 KiB
Python
import os
|
|
import re
|
|
|
|
templates_to_update = [
|
|
'src/main/resources/templates/dao-tao-detail.html',
|
|
'src/main/resources/templates/posts/full-width.html',
|
|
'src/main/resources/templates/posts/livestream.html',
|
|
'src/main/resources/templates/posts/sidebar.html',
|
|
'src/main/resources/templates/posts/standard.html'
|
|
]
|
|
|
|
# In dao-tao-detail, the loop is `blocks.forEach(function(block) {`
|
|
# In others, the loop is `data.blocks.forEach(function(block) {`
|
|
# The switch starts with `switch(block.type) {` and ends with `}` before the end of the loop.
|
|
|
|
for filepath in templates_to_update:
|
|
if not os.path.exists(filepath):
|
|
print(f"Skipping {filepath}, does not exist")
|
|
continue
|
|
|
|
with open(filepath, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
|
|
# Find the block loop start
|
|
loop_start_match = re.search(r'(data\.blocks|blocks)\.forEach\(function\(block\)\s*\{', content)
|
|
if not loop_start_match:
|
|
print(f"Loop not found in {filepath}")
|
|
continue
|
|
|
|
# We want to replace the whole forEach logic with our new state machine logic.
|
|
# But we need the existing switch cases!
|
|
switch_match = re.search(r'switch\s*\(\s*block\.type\s*\)\s*\{([\s\S]*?)default:', content)
|
|
if not switch_match:
|
|
print(f"Switch not found in {filepath}")
|
|
continue
|
|
|
|
cases_content = switch_match.group(1)
|
|
|
|
new_parser_code = """
|
|
var inTabs = false;
|
|
var tabsGroup = null;
|
|
|
|
function renderSingleBlock(block) {
|
|
var html = "";
|
|
switch(block.type) {
|
|
""" + cases_content + """
|
|
case "tabStart":
|
|
case "tabEnd":
|
|
break;
|
|
default:
|
|
console.log("Unknown block type", block.type);
|
|
}
|
|
return html;
|
|
}
|
|
|
|
var blockList = data && data.blocks ? data.blocks : (typeof blocks !== 'undefined' ? blocks : []);
|
|
var finalHtml = "";
|
|
|
|
blockList.forEach(function(block) {
|
|
if (block.type === 'tabStart') {
|
|
if (!inTabs) {
|
|
inTabs = true;
|
|
tabsGroup = { tabs: [] };
|
|
}
|
|
tabsGroup.tabs.push({
|
|
title: block.data.title || 'Tab',
|
|
contentHtml: ''
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (block.type === 'tabEnd') {
|
|
if (inTabs && tabsGroup) {
|
|
inTabs = false;
|
|
var groupHtml = '<div class="custom-tabs-wrapper">';
|
|
groupHtml += '<div class="tabs-container flex justify-center xl:mb-8 md:mb-6 mb-4" style="margin-bottom: 2rem; gap: 10px; display: flex; flex-wrap: wrap;">';
|
|
tabsGroup.tabs.forEach(function(tab, index) {
|
|
var activeClass = (index === 0) ? 'active' : '';
|
|
groupHtml += '<button class="dao-tao-tab-btn custom-tab-btn ' + activeClass + '" data-tab-idx="' + index + '" style="padding: 10px 20px; border: 1px solid #ccc; background: ' + (index===0 ? '#0055a5' : '#f8f9fa') + '; color: ' + (index===0 ? 'white' : 'black') + '; cursor: pointer;">' + tab.title + '</button>';
|
|
});
|
|
groupHtml += '</div>';
|
|
|
|
tabsGroup.tabs.forEach(function(tab, index) {
|
|
var displayStyle = (index === 0) ? 'block' : 'none';
|
|
groupHtml += '<div class="dao-tao-tab-panel custom-tab-panel" data-tab-idx="' + index + '" style="display: ' + displayStyle + ';">';
|
|
groupHtml += tab.contentHtml;
|
|
groupHtml += '</div>';
|
|
});
|
|
groupHtml += '</div>';
|
|
finalHtml += groupHtml;
|
|
tabsGroup = null;
|
|
}
|
|
return;
|
|
}
|
|
|
|
var blockHtml = renderSingleBlock(block);
|
|
|
|
if (inTabs && tabsGroup && tabsGroup.tabs.length > 0) {
|
|
tabsGroup.tabs[tabsGroup.tabs.length - 1].contentHtml += blockHtml;
|
|
} else {
|
|
finalHtml += blockHtml;
|
|
}
|
|
});
|
|
|
|
if (inTabs && tabsGroup) {
|
|
// Close unclosed tabs at the end
|
|
var groupHtml = '<div class="custom-tabs-wrapper">';
|
|
groupHtml += '<div class="tabs-container flex justify-center xl:mb-8 md:mb-6 mb-4" style="margin-bottom: 2rem; gap: 10px; display: flex; flex-wrap: wrap;">';
|
|
tabsGroup.tabs.forEach(function(tab, index) {
|
|
var activeClass = (index === 0) ? 'active' : '';
|
|
groupHtml += '<button class="dao-tao-tab-btn custom-tab-btn ' + activeClass + '" data-tab-idx="' + index + '" style="padding: 10px 20px; border: 1px solid #ccc; background: ' + (index===0 ? '#0055a5' : '#f8f9fa') + '; color: ' + (index===0 ? 'white' : 'black') + '; cursor: pointer;">' + tab.title + '</button>';
|
|
});
|
|
groupHtml += '</div>';
|
|
|
|
tabsGroup.tabs.forEach(function(tab, index) {
|
|
var displayStyle = (index === 0) ? 'block' : 'none';
|
|
groupHtml += '<div class="dao-tao-tab-panel custom-tab-panel" data-tab-idx="' + index + '" style="display: ' + displayStyle + ';">';
|
|
groupHtml += tab.contentHtml;
|
|
groupHtml += '</div>';
|
|
});
|
|
groupHtml += '</div>';
|
|
finalHtml += groupHtml;
|
|
}
|
|
|
|
html = finalHtml; // Assign back to whatever variable the original script used.
|
|
"""
|
|
|
|
# We need to replace the entire forEach loop.
|
|
# We will use regex to find the block from data.blocks.forEach up to the end of the loop.
|
|
# It's tricky to balance braces with regex. Let's do string replacement.
|
|
|
|
if filepath.endswith('dao-tao-detail.html'):
|
|
start_marker = "blocks.forEach(function(block) {"
|
|
end_marker = "html += \"</table></figure>\";\n break;"
|
|
|
|
start_idx = content.find(start_marker)
|
|
# Find the closing brace of the switch statement after end_marker
|
|
end_marker_idx = content.find(end_marker, start_idx) + len(end_marker)
|
|
|
|
# We need to replace up to the end of the forEach loop.
|
|
end_loop_idx = content.find("});", end_marker_idx) + 3
|
|
|
|
content = content[:start_idx] + new_parser_code + content[end_loop_idx:]
|
|
else:
|
|
start_marker = "data.blocks.forEach(function(block) {"
|
|
end_marker = "case \"raw\":\n html += block.data.html;\n break;"
|
|
|
|
start_idx = content.find(start_marker)
|
|
end_marker_idx = content.find(end_marker, start_idx) + len(end_marker)
|
|
end_loop_idx = content.find("});", end_marker_idx) + 3
|
|
|
|
content = content[:start_idx] + new_parser_code + content[end_loop_idx:]
|
|
|
|
# Inject tab switching script at the end of the file if not present
|
|
switch_script = """
|
|
<script>
|
|
document.addEventListener('click', function(e) {
|
|
if (e.target.classList.contains('custom-tab-btn')) {
|
|
var btn = e.target;
|
|
var container = btn.closest('.custom-tabs-wrapper');
|
|
if (!container) return;
|
|
var idx = btn.getAttribute('data-tab-idx');
|
|
|
|
container.querySelectorAll('.custom-tab-btn').forEach(function(b) {
|
|
b.classList.remove('active');
|
|
b.style.background = '#f8f9fa';
|
|
b.style.color = 'black';
|
|
});
|
|
btn.classList.add('active');
|
|
btn.style.background = '#0055a5';
|
|
btn.style.color = 'white';
|
|
|
|
container.querySelectorAll('.custom-tab-panel').forEach(function(p) {
|
|
p.style.display = 'none';
|
|
});
|
|
var activePanel = container.querySelector('.custom-tab-panel[data-tab-idx="' + idx + '"]');
|
|
if (activePanel) activePanel.style.display = 'block';
|
|
}
|
|
});
|
|
</script>
|
|
"""
|
|
if "custom-tab-btn" not in content:
|
|
content = content.replace("</body>", switch_script + "</body>")
|
|
|
|
with open(filepath, 'w', encoding='utf-8') as f:
|
|
f.write(content)
|
|
|
|
print(f"Updated {filepath}")
|
|
|