File: thumbspage/build/userguide-online-links.py

#!/usr/bin/env python3
"""
=========================================================================
User-guide local links => online links, for the program-only zip [2.1].
Part of the thumbspage program (learning-python.com/thumbspage.html).

Replace all local 'example/' URLs in UserGuide.html with online URLs.
This script creates a new file for its result, UserGuideLive.html.
Run me from anywhere (it uses the script's own dir explicitly, not cwd).
An inverse function can also unpatch the live links, if ever needed.

At 246M in 2.1, the examples/ folder may be better accessed online,
but links to it in the user guide need to use either local or online 
content.  To support both, local links (href="examples/) are always
used when writing the guide, and this script is run at build time to
change all examples/ links to point online instead (href="https://...).

HTML has no notion of variables; the guide could use a tag replaced on
demand, but this make it difficult to view content being developed, and
JavaScript is a nonstarter for this document.  No other HTML files can
use local examples/ links (they're elsewhere in the site).  This script 
also looks for any online links in original (they should all be locals).

Note: the user guide also references other top-level items besides 
examples/ content (e.g., docetc/ images, build/ scripts, and top-level
code files), so it cannot be shipped with the examples-only zip.  The 
program zip is everything but examples/, so these links work.  They 
could be changed to online links too, but examples/ is the real size hog.

Verification of Apr-2022 changes here (using UserGuideLive at ?? ahead):
.../thumbspage$ rm -f UserGuideLive.html UserGuideLocal.html 
.../thumbspage$ cd build/
.../thumbspage/build$ py3 userguide-online-links.py > /dev/null
.../thumbspage/build$ py3 userguide-online-links.py - > /dev/null
.../thumbspage/build$ cd ..
.../thumbspage$ diff UserGuide.html UserGuideLocal.html 
.../thumbspage$ diff UserGuideLive.html progzip/thumbspage/UserGuide.html
.../thumbspage$ 
=========================================================================
"""
import os, sys
trace = lambda *args, **kargs: print(' '*4, *args, **kargs)
mydir = os.path.dirname(__file__)


def patchFile(fromfile, tofile, fromkey, tokey):
    """
    -----------------------------------------------
    Replace all fromkey with tokey in fromfile, put
    result in tofile.  Trace lines, return #changed.
    -----------------------------------------------
    """
    orig = open(fromfile, 'r', encoding='utf8')
    copy = open(tofile,   'w', encoding='utf8')

    patches = 0
    for line in orig:
        if fromkey in line:
            trace(line, end='')
            patches += 1
            line = line.replace(fromkey, tokey)
        copy.write(line)

    orig.close()
    copy.close()
    return patches


localLink  = '="examples'
onlineLink = '="https://learning-python.com/thumbspage/examples'


def patchOnlineToLocal():
    """
    -----------------------------------------------
    Revert online=>local links in a new doc copy.
    Use this to undo patchLocalToOnline's output.
    -----------------------------------------------
    """
    print('Unpatched lines:')

    source = os.path.join(mydir, '..', 'UserGuide.html')        # or UserGuideLive??
    dest   = os.path.join(mydir, '..', 'UserGuideLocal.html')

    patches = patchFile(source, dest, fromkey=onlineLink, tokey=localLink)
    print('Lines unpatched:', patches)


def patchLocalToOnline():
    """
    -----------------------------------------------
    Change local=>online links in a new doc copy.
    This could be a sed command, of course, but
    Py is more portable and flexible (and funner). 
    -----------------------------------------------
    """
    print('Patched lines:')

    source = os.path.join(mydir, '..', 'UserGuide.html')
    dest   = os.path.join(mydir, '..', 'UserGuideLive.html')

    patches = patchFile(source, dest, fromkey=localLink, tokey=onlineLink)
    print('Lines patched:', patches)


def findLurkers():
    """
    -----------------------------------------------
    Are there any online links in the original?
    There were 4 initially, plus 2 valid refs.
    -----------------------------------------------
    """
    print('Finding lurkers')
    source = os.path.join(mydir, '..', 'UserGuide.html')

    local1 = '="examples'
    orig = open(source, 'r', encoding='utf8')
    l1 = [line for line in orig if local1 in line]
    print('Local links:', len(l1))

    local2 = 'examples/'
    orig = open(source, 'r', encoding='utf8')
    l2 = [line for line in orig if local2 in line]
    print('Possible online links:', len(l2))

    lurkers = set(l2) - set(l1)
    if lurkers: 
        print('Possible online links in original:', len(l2) - len(l1)) 
        for line in lurkers:
            trace(line, end='')
        print()


if __name__ == '__main__':
    findLurkers()               # report before changes
    if len(sys.argv) > 1:
        patchOnlineToLocal()    # any arg: undo patched online links
    else:
        patchLocalToOnline()    # normal run: patch local=>online links
 



"""
==============================================================================
Output:

~/MY-STUFF/Code/thumbspage/build$ python3 userguide-online-links.py
Finding lurkers
Local links: 268
Possible online links: 274
Possible online links in original: 6
     <A HREF="http://learning-python.com/thumbspage/examples/reorientation/index.html">here</A>
     ...

Patched lines:
     packaged <A HREF="examples/">examples</A>, 
     <A HREF="examples/2.0-upgrades/fullscreen-no-ios13-hidetoolbar2.jpeg">browser</A>.
     <A HREF="examples/unicode/images/index.html">index page</A> with generated 
     ...
Lines patched: 268
==============================================================================
"""



[Home page] Books Code Blog Python Author Train Find ©M.Lutz