Modify

Opened 4 years ago

Closed 3 years ago

Last modified 3 years ago

#13871 closed defect (wontfix)

Use css from configured htdocs dir/location

Reported by: anonymous Owned by: Jun Omae
Priority: normal Component: TracHtmlNotificationPlugin
Severity: normal Keywords:
Cc: Trac Release:

Description

I have custom configured htdocs files, which contain a change to the color scheme. Maybe this isn't the best way to do this, but it works OK with Trac proper. However, this really cool plugin seems to ignore the custom files and go right for the stock files.

My "global" configuration file from which all projects inherit has something like this ...

[trac]
htdocs_location = /tracstatic/chrome_common

[inherit]
htdocs_dir = <blahblahblah>/tracstatic/chrome_common

I found fairly quickly that the plugin is looking for "common" in its get_styles() function, but the custom stuff is under "shared".

So, to get around the problem, I duplicated the whole contents of the function and search for "shared" first, before looking for "common". Then it will pick up the custom files and will look the same as a Trac page. (There are probably nicer ways to approach the issue. Sorry.)

    def _get_styles(self, chrome):
        # Added search for 'shared' to get configured css
        for provider in chrome.template_providers:
            for prefix, dir in provider.get_htdocs_dirs():
                if prefix != 'shared':
                    continue
                url_re = re.compile(r'\burl\([^\]]*\)')
                buf = ['#content > hr { display: none }']
                for name in ('trac.css', 'ticket.css'):
                    f = open(os.path.join(dir, 'css', name))
                    try:
                        lines = f.read().splitlines()
                    finally:
                        f.close()
                    buf.extend(url_re.sub('none', to_unicode(line))
                               for line in lines
                               if not line.startswith('@import'))
                return ('/*<![CDATA[*/\n' +
                        '\n'.join(buf).replace(']]>', ']]]]><![CDATA[>') +
                        '\n/*]]>*/')

        for provider in chrome.template_providers:
            for prefix, dir in provider.get_htdocs_dirs():
                if prefix != 'common':
                    continue
                url_re = re.compile(r'\burl\([^\]]*\)')
                buf = ['#content > hr { display: none }']
                for name in ('trac.css', 'ticket.css'):
                    f = open(os.path.join(dir, 'css', name))
                    try:
                        lines = f.read().splitlines()
                    finally:
                        f.close()
                    buf.extend(url_re.sub('none', to_unicode(line))
                               for line in lines
                               if not line.startswith('@import'))
                return ('/*<![CDATA[*/\n' +
                        '\n'.join(buf).replace(']]>', ']]]]><![CDATA[>') +
                        '\n/*]]>*/')
        return ''

Attachments (0)

Change History (9)

comment:1 Changed 4 years ago by anonymous

Sorry, I forgot to mention that this is for Trac 1.4.2

comment:2 Changed 4 years ago by Ryan J Ollos

Maybe the following would be the best fix:

if prefix not in ('shared', 'common'):

comment:3 Changed 3 years ago by Jun Omae

Resolution: wontfix
Status: newclosed

I cannot accept proposed design. Closing by #13105.

comment:4 Changed 3 years ago by Dan

Resolution: wontfix
Status: closedreopened

Jun, thanks for your feedback, but it's not entirely clear to me what the problem is.

Ryan, your suggestion would make for much cleaner code, but doesn't work, because common will come first and be used instead of shared (there is a return statement within the loop).

Without this patch, the e-mails come out red, like Trac's colors, not blue, like the configured custom colors that are usually used for tickets in the web interface. Even with Ryan's suggestion, as I mentioned, the non-custom red color is used.

Is the objection about using "shared" at all? Or just the un-maintainability?

Here's a more succinct version that works:

    def _get_styles(self, chrome):
        ok_dirs = {}
        for provider in chrome.template_providers:
            for prefix, dir in provider.get_htdocs_dirs():
                if prefix in ('shared', 'common'):
                    ok_dirs[prefix] = dir
        if len(ok_dirs) > 0:
            # Try "shared" if it is found, to capture custom formatting.
            dir = ok_dirs['shared'] if 'shared' in ok_dirs else list(ok_dirs.values())[0]
            url_re = re.compile(r'\burl\([^\]]*\)')
            buf = ['#content > hr { display: none }']
            for name in ('trac.css', 'ticket.css'):
                f = open(os.path.join(dir, 'css', name), encoding='utf-8')
                try:
                    lines = f.read().splitlines()
                finally:
                    f.close()
                buf.extend(url_re.sub('none', to_unicode(line))
                           for line in lines
                           if not line.startswith('@import'))
            return ('/*<![CDATA[*/\n' +
                    '\n'.join(buf).replace(']]>', ']]]]><![CDATA[>') +
                    '\n/*]]>*/')
        return ''

Clarification would be appreciated.

comment:5 Changed 3 years ago by Dan

OK, I think I'm grokking the problem. I need to account for the case where there are no customized files.

Here's another try.

    def _get_styles(self, chrome):
        ok_prefixes = ('shared', 'common')
        ok_dirs = {}
        for provider in chrome.template_providers:
            for prefix, dir in provider.get_htdocs_dirs():
                if prefix in ok_prefixes:
                    ok_dirs[prefix] = dir

        url_re = re.compile(r'\burl\([^\]]*\)')
        buf = ['#content > hr { display: none }']

        # Try "shared" provider first to use any custom formatting.
        for prefix in ok_prefixes:
            if prefix in ok_dirs:
                filenames = [os.path.join(ok_dirs[prefix], 'css', name) 
                            for name in ('trac.css', 'ticket.css')]
                if not os.path.isfile(filenames[0]):
                    continue
                for name in filenames:
                    f = open(name, encoding='utf-8')
                    try:
                        lines = f.read().splitlines()
                    finally:
                        f.close()
                    buf.extend(url_re.sub('none', to_unicode(line))
                               for line in lines
                               if not line.startswith('@import'))
                return ('/*<![CDATA[*/\n' +
                        '\n'.join(buf).replace(']]>', ']]]]><![CDATA[>') +
                        '\n/*]]>*/')
        return ''

comment:6 Changed 3 years ago by Dan

Here's an alternative that is a bit more robust:

    def _get_styles(self, chrome):
        ok_prefixes = ('shared', 'common')
        ok_dirs = {}
        for provider in chrome.template_providers:
            for prefix, dir in provider.get_htdocs_dirs():
                if prefix in ok_prefixes:
                    ok_dirs[prefix] = dir

        # Try "shared" provider first to use any custom formatting.
        for prefix in ok_prefixes:
            if prefix in ok_dirs:
                try:
                    url_re = re.compile(r'\burl\([^\]]*\)')
                    buf = ['#content > hr { display: none }']
                    for name in ('trac.css', 'ticket.css'):
                        f = open(os.path.join(ok_dirs[prefix], 'css', name), 
                                 encoding='utf-8')
                        try:
                            lines = f.read().splitlines()
                        finally:
                            f.close()
                        buf.extend(url_re.sub('none', to_unicode(line))
                                   for line in lines
                                   if not line.startswith('@import'))
                    return ('/*<![CDATA[*/\n' +
                            '\n'.join(buf).replace(']]>', ']]]]><![CDATA[>') +
                            '\n/*]]>*/')
                except FileNotFoundError:
                    continue
        return ''

comment:7 Changed 3 years ago by figaro

Can you post your update as a diff file and add the keyword 'patch' to this ticket? That will help to apply the patch and test it.

comment:8 Changed 3 years ago by Jun Omae

Resolution: wontfix
Status: reopenedclosed

I'll remove style element by #13105.

comment:9 Changed 3 years ago by Dan

Thanks. :)

When I see the change, I'll incorporate it into TicketReminderPlugin, into which I transplanted this code.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain Jun Omae.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.