|
4 | 4 | <meta charset="UTF-8" /> |
5 | 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
6 | 6 | <title>Pages</title> |
| 7 | + <meta |
| 8 | + http-equiv="Cache-Control" |
| 9 | + content="no-cache, no-store, must-revalidate" |
| 10 | + /> |
| 11 | + <meta http-equiv="Pragma" content="no-cache" /> |
| 12 | + <meta http-equiv="Expires" content="0" /> |
7 | 13 | <style> |
8 | 14 | :root { |
9 | 15 | --primary: #0082c9; |
|
415 | 421 | <script src="https://cdn.jsdelivr.net/npm/marked@4.2.12/marked.min.js"></script> |
416 | 422 |
|
417 | 423 | <script type="module"> |
| 424 | + // Add a random version to prevent caching |
| 425 | + console.log('Loading page editor v' + Math.random()) |
| 426 | + |
| 427 | + // Test the filename conversion |
| 428 | + function testFilenameConversion() { |
| 429 | + const testCases = [ |
| 430 | + 'project/test', |
| 431 | + 'foo/bar/baz', |
| 432 | + 'test-page', |
| 433 | + 'another_test' |
| 434 | + ] |
| 435 | + |
| 436 | + console.log('======= TESTING FILENAME CONVERSION =======') |
| 437 | + testCases.forEach(test => { |
| 438 | + console.log( |
| 439 | + `Original: "${test}" -> Converted: "${test.replace(/\//g, '___')}"` |
| 440 | + ) |
| 441 | + }) |
| 442 | + console.log('==========================================') |
| 443 | + } |
| 444 | + |
| 445 | + // Run the test immediately |
| 446 | + testFilenameConversion() |
| 447 | + |
418 | 448 | // Import navbar and nosdav shim |
419 | 449 | import Navbar from './navbar.js' |
420 | 450 | import './nosdav-shim.js' |
|
445 | 475 | }, |
446 | 476 | renderer(token) { |
447 | 477 | const pageName = token.text |
448 | | - const safePageName = pageName |
449 | | - .replace(/[^a-zA-Z0-9-_]/g, '-') |
450 | | - .toLowerCase() |
| 478 | + console.log('Wiki link pageName:', pageName) |
| 479 | + |
| 480 | + // Use the consistent utility function for safe file names |
| 481 | + const safePageName = PageUtils.toSafeFilename(pageName) |
| 482 | + console.log('Wiki link safePageName:', safePageName) |
| 483 | + |
451 | 484 | const href = `../pages/${safePageName}.md` |
452 | 485 | return `<a href="#" class="wiki-link" data-page="${pageName}">[[${pageName}]]</a>` |
453 | 486 | } |
|
473 | 506 | PREVIEW: 'preview' |
474 | 507 | } |
475 | 508 |
|
| 509 | + // Utility functions for page name to file path conversion |
| 510 | + const PageUtils = { |
| 511 | + // Convert a page name to a safe file path |
| 512 | + toSafeFilename(pageName) { |
| 513 | + console.log('Converting filename:', pageName) |
| 514 | + // IMPORTANT: Only replace slashes with triple underscores, preserve all other characters |
| 515 | + const result = pageName.replace(/\//g, '___') |
| 516 | + console.log('Result after conversion:', result) |
| 517 | + return result |
| 518 | + }, |
| 519 | + |
| 520 | + // Get the full path for a page name |
| 521 | + getPagePath(pageName) { |
| 522 | + const safePageName = this.toSafeFilename(pageName) |
| 523 | + const path = `public/pages/${safePageName}.md` |
| 524 | + console.log('Final path:', path) |
| 525 | + return path |
| 526 | + } |
| 527 | + } |
| 528 | + |
476 | 529 | // Page storage utilities |
477 | 530 | const PageStorage = { |
478 | 531 | getPagePath(pageName) { |
479 | | - // Handle spaces and special characters for filenames |
480 | | - const safePageName = pageName |
481 | | - .replace(/[^a-zA-Z0-9-_]/g, '-') |
482 | | - .toLowerCase() |
483 | | - return `public/pages/${safePageName}.md` |
| 532 | + // Use the utility function for consistent path handling |
| 533 | + console.log('Getting path for page:', pageName) |
| 534 | + return PageUtils.getPagePath(pageName) |
484 | 535 | }, |
485 | 536 |
|
486 | 537 | async savePage(pageName, content) { |
| 538 | + console.log('Saving page with name:', pageName) |
487 | 539 | const path = this.getPagePath(pageName) |
| 540 | + console.log('Using file path:', path) |
488 | 541 |
|
489 | 542 | try { |
490 | 543 | // Save to nosdav |
|
522 | 575 | }, |
523 | 576 |
|
524 | 577 | async getPage(pageName) { |
| 578 | + console.log('Getting page with name:', pageName) |
525 | 579 | const path = this.getPagePath(pageName) |
| 580 | + console.log('Looking up file path:', path) |
526 | 581 |
|
527 | 582 | try { |
528 | 583 | // Try to get from nosdav |
|
534 | 589 | } |
535 | 590 |
|
536 | 591 | const url = `https://nosdav.net/${pubkey}/${path}` |
| 592 | + console.log('Fetching from URL:', url) |
537 | 593 | const response = await fetch(url) |
538 | 594 |
|
539 | 595 | if (response.status === 404) { |
| 596 | + console.log('Page not found (404)') |
540 | 597 | return '' |
541 | 598 | } |
542 | 599 |
|
|
660 | 717 | if (e.target.classList.contains('wiki-link')) { |
661 | 718 | e.preventDefault() |
662 | 719 | const pageName = e.target.dataset.page |
| 720 | + console.log('Clicked wiki link for page:', pageName) |
663 | 721 | if (pageName) { |
664 | 722 | setCurrentPage(pageName) |
665 | 723 | } |
|
728 | 786 | // Navigate to page |
729 | 787 | const navigateToPage = () => { |
730 | 788 | if (pageInput.trim()) { |
| 789 | + console.log('Navigating to page:', pageInput.trim()) |
731 | 790 | setCurrentPage(pageInput.trim()) |
732 | 791 | } |
733 | 792 | } |
|
761 | 820 | } |
762 | 821 | } |
763 | 822 |
|
| 823 | + // Debug function to test path conversion |
| 824 | + const testPathConversion = () => { |
| 825 | + const testPath = prompt( |
| 826 | + 'Enter a test path (e.g. foo/bar):', |
| 827 | + 'project/test' |
| 828 | + ) |
| 829 | + if (testPath) { |
| 830 | + const converted = PageUtils.toSafeFilename(testPath) |
| 831 | + const fullPath = PageUtils.getPagePath(testPath) |
| 832 | + alert( |
| 833 | + `Original: ${testPath}\nConverted: ${converted}\nFull path: ${fullPath}` |
| 834 | + ) |
| 835 | + } |
| 836 | + } |
| 837 | + |
764 | 838 | // Helper function to insert wiki link at cursor |
765 | 839 | const insertWikiLink = () => { |
766 | 840 | if (!editorRef.current) return |
|
770 | 844 | const end = textarea.selectionEnd |
771 | 845 | const selectedText = textarea.value.substring(start, end) |
772 | 846 |
|
773 | | - // Prepare the wiki link text - either use selection or placeholder |
774 | | - const linkText = selectedText || 'page-name' |
| 847 | + // Prepare the wiki link text - either use selection or prompt for a hierarchical page name |
| 848 | + let linkText |
| 849 | + if (selectedText) { |
| 850 | + linkText = selectedText |
| 851 | + } else { |
| 852 | + linkText = prompt( |
| 853 | + 'Enter page name (can use foo/bar format):', |
| 854 | + 'page-name' |
| 855 | + ) |
| 856 | + if (!linkText) return // User canceled the prompt |
| 857 | + } |
| 858 | + |
775 | 859 | const wikiLink = `[[${linkText}]]` |
776 | 860 |
|
777 | 861 | // Insert the wiki link at the cursor position |
|
961 | 1045 | ></path> |
962 | 1046 | </svg> |
963 | 1047 | </div> |
| 1048 | +
|
| 1049 | + <!-- Debug button --> |
| 1050 | + <div |
| 1051 | + class="view-option" |
| 1052 | + onClick=${testPathConversion} |
| 1053 | + title="Test Path Conversion" |
| 1054 | + style="background-color: #f97316;" |
| 1055 | + > |
| 1056 | + <svg |
| 1057 | + width="16" |
| 1058 | + height="16" |
| 1059 | + viewBox="0 0 24 24" |
| 1060 | + fill="none" |
| 1061 | + stroke="white" |
| 1062 | + stroke-width="2" |
| 1063 | + stroke-linecap="round" |
| 1064 | + stroke-linejoin="round" |
| 1065 | + > |
| 1066 | + <path |
| 1067 | + d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" |
| 1068 | + ></path> |
| 1069 | + </svg> |
| 1070 | + </div> |
964 | 1071 | </div> |
965 | 1072 | </div> |
966 | 1073 | <div class="page-nav"> |
|
0 commit comments