Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.
HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Release Notes</title>
</head>
<body style="margin:0; padding:0; font-family: Arial, Helvetica, sans-serif; background:#ffffff;">
  <div style="max-width:1200px; margin:0 auto; padding:16px;">
    <div style="border:1px solid #dfe1e6; border-radius:8px; overflow:hidden;">
      <div style="background:#0052CC; color:#fff; padding:14px 16px;">
        <div style="display:flex; align-items:center; gap:12px;">
          <!-- TOTVS logo (anexo do Confluence/TDN):
               - Nome do anexo: "totvs logo.jpg"
               - O JS abaixo tenta carregar primeiro do pageId atual, e cai em fallback se não achar -->
          <img
            id="totvs-logo"
            alt="TOTVS"
            style="display:none; height:28px; width:auto; background:#ffffff; border-radius:6px; padding:4px; border:1px solid rgba(255,255,255,0.35);"
          />
          <div id="page-title" style="font-size:18px; font-weight:700;">Dicionário de Dados</div>
        </div>
      </div>

      <div style="background:#f4f5f7; border-top:1px solid #dfe1e6; padding:12px 16px; display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
        <div style="display:flex; gap:8px; align-items:center;">
          <div style="font-weight:700; color:#172b4d;">Versão:</div>
          <div id="version-display" style="background:#fff; border:1px solid #dfe1e6; border-radius:6px; padding:4px 10px; font-weight:700; color:#172b4d;">-</div>
        </div>

        <div style="display:flex; gap:8px; align-items:center;">
          <div style="font-weight:700; color:#172b4d;">Atualizado:</div>
          <div id="last-update" style="background:#fff; border:1px solid #dfe1e6; border-radius:6px; padding:4px 10px; color:#172b4d;">-</div>
        </div>

        <a id="doc-link" href="#" target="_blank" style="display:none; margin-left:auto; text-decoration:none; background:#ffffff; color:#0052CC; border:1px solid #0052CC; border-radius:6px; padding:6px 10px; font-weight:700;">
          Abrir no Drive
        </a>
      </div>

      <div id="widget-container" style="min-height:520px; background:#ffffff;">
        <div style="padding:18px; color:#6b778c;">Carregando documento...</div>
      </div>
    </div>
  </div>

  <script>
  (function() {
    // Fonte: GitHub (RAW)
    // Repo: https://github.com/Juansimeoni/ReleaseDatasul
    // Arquivo esperado: {versao}.txt (ex: 12.1.2503.15.txt)
    const GITHUB_RAW_BASEOWNER = 'https://raw.githubusercontent.com/Juansimeoni/ReleaseDatasul/main/';

    const function getPageVersion() {GITHUB_REPO = 'ReleaseDatasul';
    const GITHUB_BRANCH = 'main';
    const versionPatternGITHUB_PATH_PREFIX = ''; /(\d+\.\d+\.\d+(?:\.\d+)?)/;

// ex: 'releases' (sem / no início e no fim)

    const GITHUB_RAW_BASE = 'https://raw.githubusercontent.com/' + GITHUB_OWNER + '/' + GITHUB_REPO + '/' + GITHUB_BRANCH + '/';
    const GITHUB_BLOB_BASE = 'https://github.com/' + GITHUB_OWNER + '/' + GITHUB_REPO + '/blob/' + GITHUB_BRANCH + '/';
    const GITHUB_API_BASE = 'https://api.github.com/repos/' + GITHUB_OWNER + '/' + GITHUB_REPO + '/';

    function buildRepoPath(version) {
      const filename = version + '.txt';
      return GITHUB_PATH_PREFIX ? (GITHUB_PATH_PREFIX + '/' + filename) : filename;
    }

    function setLastUpdateText(text) {
      const el = document.getElementById('last-update');
      if (el) el.textContent = text || '-';
    }

    function formatDatePtBr(value) {
      try {
        const d = new Date(value);
        if (isNaN(d.getTime())) return null;
        return d.toLocaleString('pt-BR');
      } catch (e) {
        return null;
      }
    }

    function tryFetchCommitDate(pathInRepo) {
      // Busca o último commit do arquivo (public repo, sem token)
      // Endpoint: /commits?path=...&sha=...&per_page=1
      const url = GITHUB_API_BASE + 'commits?path=' + encodeURIComponent(pathInRepo) +
        '&sha=' + encodeURIComponent(GITHUB_BRANCH) + '&per_page=1';

      return fetch(url, { cache: 'no-store' })
        .then(function(resp) {
          if (!resp.ok) return null;
          return resp.json();
        })
        .then(function(arr) {
          if (!arr || !arr.length) return null;
          const c = arr[0] || {};
          const commit = c.commit || {};
          const committer = commit.committer || {};
          const author = commit.author || {};
          // prefer committer date, fallback author date
          return committer.date || author.date || null;
        })
        .catch(function() {
          return null;
        });
    }

    function getPageVersion() {
      const versionPattern = /(\d+\.\d+\.\d+(?:\.\d+)?)/;

      const pageTitleElement = document.querySelector('h1#title-text, .page-title, h1, [data-page-title]');
      if (pageTitleElement) {
        const titleText = (pageTitleElement.textContent || '').trim();
        const match = titleText.match(versionPattern);
        if (match) return match[1];
      }

      const metaTitle = document.querySelector('meta[property="og:title"], meta[name="title"]');
      if (metaTitle) {
        const titleText = metaTitle.getAttribute('content') || '';
        const match = titleText.match(versionPattern);
        if (match) return match[1];
      }

      const titleMatch = (document.title || '').match(versionPattern);
      if (titleMatch) return titleMatch[1];

      return null;
    }

    function getPageId() {
      try {
        const pageTitleElementqs = document.querySelector('h1#title-text, .page-title, h1, [data-page-title]');
 new URLSearchParams(window.location.search);
        const if (pageTitleElement) {fromQuery = qs.get('pageId');
        constif titleText = (pageTitleElement.textContent || '').trim((fromQuery) return String(fromQuery);
      }  const match = titleText.match(versionPattern);
        if (match) return match[1];catch (e) { /* ignore */ }

      // Confluence costuma expor isso quando AJS está disponível
      }

try {
         const metaTitle = document.querySelector('meta[property="og:title"], meta[name="title"]');
if (window.AJS && AJS.params && AJS.params.pageId) return String(AJS.params.pageId);
      } ifcatch (metaTitlee) { /* ignore */ }

      return  const titleText = metaTitle.getAttribute('content') || '';
  null;
    }

    function setTotvsLogo() {
      const matchlogoEl = titleTextdocument.match(versionPatterngetElementById('totvs-logo');
        if (match!logoEl) return match[1];
      }

      const titleMatchpageId = (document.title || '').match(versionPattern)getPageId();
      const iffilename (titleMatch) return titleMatch[1];

= 'totvs logo.jpg';
      const encodedName return null= encodeURIComponent(filename);

    }

  const candidates function getPageId() {= [];
      tryif (pageId) {
        const// qsthumbnails =costuma new URLSearchParams(window.location.search);
   funcionar melhor no Confluence
     const fromQuery = qscandidates.getpush('pageId');
        if (fromQuery) return String(fromQuery)/download/thumbnails/' + pageId + '/' + encodedName + '?api=v2');
      } catch (e) { /* ignore */ }

      // Confluence costuma expor isso quando AJS está disponívelcandidates.push('/download/attachments/' + pageId + '/' + encodedName);
      }
      try {
        if (window.AJS && AJS.params && AJS.params.pageId) return String(AJS.params.pageId);
// fallback: página “principal” antiga (se existir o anexo lá também)
      candidates.push('/download/attachments/649987902/' + encodedName);

      }let catchidx (e) { /* ignore */ }

      return null;
= 0;
      function tryNext() {
       }

 if (idx  function setTotvsLogo(>= candidates.length) {return;
        const logoElurl = document.getElementById('totvs-logo');
candidates[idx++];
        if (!logoEl) return;

const probe = new Image();
       const pageIdprobe.onload = getPageIdfunction(); {
      const filename = 'totvs logo.jpg'logoEl.src = url;
         const encodedNamelogoEl.style.display = encodeURIComponent(filename);
'inline-block';
      const candidates = []};
       if (pageId probe.onerror = function() {
         // thumbnails costuma funcionar melhor no Confluence tryNext();
        };
        candidates.push('/download/thumbnails/' + pageId + '/' + encodedName + '?api=v2'probe.src = url;
      }

      tryNext();
    }

    candidates.push('/download/attachments/' + pageId + '/' + encodedName);
/ Tenta resolver o logo mesmo antes de identificar versão/documento
    setTotvsLogo();

    function renderNotAvailable() }{
      // fallback: página “principal” antiga (se existir Mantém o anexolink (se tambémexistir)
 para permitir abrir manualmente  candidates.push('/download/attachments/649987902/' + encodedName);

no GitHub
      let idx = 0;
container.innerHTML =
        function tryNext() {
        if (idx >= candidates.length) return;
        const url = candidates[idx++];
  '<div style="padding:18px; border-left:4px solid #FFAB00; background:#FFFAE6; color:#172b4d;">' +
          '<div style="font-weight:700;">Esse documento ainda não está disponível no momento.</div>' +
      const probe = new Image() '</div>';
    }

    probe.onload = functionfunction getVersionOverrideFromQuery() {
      try {
   logoEl.src = url;
   const qs =     logoEl.style.display = 'inline-block';
        };
new URLSearchParams(window.location.search);
        const v = probe.onerror = function() {qs.get('version') || qs.get('versao');
        if  tryNext();
        }(v && /^\d+\.\d+\.\d+(?:\.\d+)?$/.test(v)) return v;
      }  probe.src = url;
      }

catch (e) { /* ignore */ }
      tryNext()return null;
    }

    //const Tentaversion resolver o logo mesmo antes de identificar versão/documento
= getPageVersion();
     setTotvsLogo(const container = document.getElementById('widget-container');

    const docLink function= renderNotAvailable() {document.getElementById('doc-link');

    const versionResolved // Mantém o link (se existir) para permitir abrir manualmente no GitHub= getVersionOverrideFromQuery() || version;

    if (!versionResolved) {
      container.innerHTML =
        '<div style="padding:18px; border-left:4px solid #FFAB00#DE350B; background:#FFFAE6#FFEBE6; color:#172b4d;">' +
          '<div style="font-weight:700;">Esse documento ainda não está disponível no momento.< margin-bottom:6px;">Versão não identificada</div>' +
          '<div>Coloque a versão no título da página, ex: <b>Dicionário de Dados 12.1.2503.14</b></div>' +
        '</div>';
    }

  return;
  function getVersionOverrideFromQuery() {
      try {}

        const qs = new URLSearchParams(window.location.search)document.getElementById('version-display').textContent = versionResolved;
        const v = qs.get('version') || qs.get('versao');
        if (v && /^\d+\.\d+\.\d+(?:\.\d+)?$/.test(v)) return v;
      } catch (e) { /* ignore */ }
      return nulldocument.getElementById('page-title').textContent = 'Dicionário de Dados ' + versionResolved;
    setLastUpdateText(new Date().toLocaleString('pt-BR'));

    const pathInRepo = buildRepoPath(versionResolved);
    const rawUrl = GITHUB_RAW_BASE + pathInRepo;
    }

const blobUrl = GITHUB_BLOB_BASE const version = getPageVersion();
    const container = document.getElementById('widget-container');
    const docLink = document.getElementById('doc-link');
+ pathInRepo;

    // Link para o GitHub (visual)
    docLink.href = blobUrl;
    constdocLink.textContent versionResolved = getVersionOverrideFromQuery() || version;
'Abrir no GitHub';
    if (!versionResolved) {docLink.style.display = 'inline-block';

      container.innerHTML =
        '<div style="padding:18px; border-left:4px solid #DE350B; background:#FFEBE6; color:#172b4d#6b778c;">'>Carregando +
conteúdo do GitHub...</div>';

        '<div style="font-weight:700; margin-bottom:6px;">Versão não identificada</div>' +fetch(rawUrl, { cache: 'no-store' })
      .then(function(resp) {
   '<div>Coloque   a versão no título da página, ex: <b>Dicionário de Dados 12.1.2503.14</b></div>' +if (!resp.ok) return { ok: false, text: '', lastModified: null };
        '</div>';
      return;
const lm = resp.headers ? resp.headers.get('last-modified') : null;
     }

   return document.getElementById('version-display').textContent = versionResolved;
    document.getElementById('page-title').textContent = 'Dicionário de Dados ' + versionResolvedresp.text().then(function(t) {
          return { ok: true, text: t, lastModified: lm };
    document.getElementById('last-update').textContent = new Date().toLocaleString('pt-BR'   });

     const rawUrl})
 = GITHUB_RAW_BASE + versionResolved + '.txt';.then(function(res) {
        const blobUrltxt = 'https://github.com/Juansimeoni/ReleaseDatasul/blob/main/' + versionResolved + '.txt';
((res && res.text) ? res.text : '').trim();
    // Link para o GitHubif (visual!txt) {
    docLink.href = blobUrl;
    docLink.textContent = 'Abrir no GitHub';
renderNotAvailable();
        docLink.style.display = 'inline-block'return;

       container.innerHTML =}

        '<div style="padding:18px; color:#6b778c;">Carregando conteúdo do GitHub...</div>';

    fetch(rawUrl, { cache: 'no-store' }// 1) Fallback rápido: Last-Modified do RAW (não é exatamente "commit date", mas aproxima)
      .then(function(resp) {
 const lm = res && res.lastModified ? if formatDatePtBr(!respres.oklastModified) return: ''null;
        return resp.text(if (lm) setLastUpdateText(lm);

      })
      .then(function(txt) {
        txt = (txt || '').trim();// 2) Data real do commit via GitHub API (se permitido por CSP)
        if (!txttryFetchCommitDate(pathInRepo).then(function(commitIso) {
          renderNotAvailable();
const formatted = commitIso ? formatDatePtBr(commitIso) : null;
          if  return(formatted) setLastUpdateText(formatted);
        });

        // Renderiza texto em <pre> preservando formatação
        const pre = document.createElement('pre');
        pre.style.whiteSpace = 'pre-wrap';
        pre.style.margin = '0';
        pre.style.padding = '16px';
        pre.style.borderTop = '1px solid #dfe1e6';
        pre.style.fontFamily = 'Consolas, Menlo, Monaco, \"Courier New\", monospace';
        pre.textContent = txt;

        container.innerHTML = '';
        container.appendChild(pre);
      })
      .catch(function() {
        renderNotAvailable();
      });
  })(); 
  </script>
</body>
</html>

...