Bug 102278 - Support CSS counters
Summary: Support CSS counters
Status: NEW
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: Writer (show other bugs)
Version:
(earliest affected)
5.2.1.2 release
Hardware: All All
: medium enhancement
Assignee: Not Assigned
URL:
Whiteboard:
Keywords: filter:html
Depends on:
Blocks: HTML-Import
  Show dependency treegraph
 
Reported: 2016-09-19 13:35 UTC by Konstantin Kharlamov
Modified: 2023-04-21 16:31 UTC (History)
2 users (show)

See Also:
Crash report or crash signature:


Attachments
A testing document (451 bytes, text/html)
2016-09-19 13:35 UTC, Konstantin Kharlamov
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Konstantin Kharlamov 2016-09-19 13:35:58 UTC
Created attachment 127428 [details]
A testing document

Content of a counter is not inserted.

For example, here I attached a simple html. Upon opening in a browser, you'd see every heading is enumerated. However, you won't see enumeration at all upon opening the same file in `lowriter`
Comment 1 Buovjaga 2016-10-09 10:37:40 UTC
I confirm.

https://www.w3.org/TR/CSS21/generate.html#counters

Arch Linux 64-bit, KDE Plasma 5
Version: 5.3.0.0.alpha0+
Build ID: ff2a399b61f34f7920e594e8cbb6c19045b24956
CPU Threads: 8; OS Version: Linux 4.7; UI Render: default; 
Locale: fi-FI (fi_FI.UTF-8); Calc: group
Built on October 7th 2016
Comment 2 Konstantin Kharlamov 2017-10-01 13:21:11 UTC
I took an attempt to fix this, but at this point I think I gotta move on — at least for now. I think it's worth to put my findings here in case anybody want to try fixing this — or may be if I try returning here at some point.

• calc's html import has a newer CSS parser, which ideally should be used. I was told on IRC that writer's html filter is very-very old — peoples are actually surprised there is a CSS parser.
• the filter probably supports only CSS1 version. It is made so explicit that "CSS1" infix is everywhere — even in filenames! You can though just ignore it, and add newer features.
• the filter code is mediocre — a bunch of global variables, unused variables, over-engineering with abstractions — it's hard to explore. 
• Before taking on CSS counters you need to add support for ":before" and ":after" selectors and "content:" function.
• Full CSS rule (i.e. selector plus body) being parsed at ParseRule()
• Parsing selectors (the part before "{") happens at ParseSelector(), and its only influence to the outside world through returned value; which is passed to SelectorParsed(), and afterwards gets deleted.
  Now, here's an important and cool twist which guaranteed to grant you many hours of confusion: inside CSS1Parser::ParseRule() you see a call to SelectorParsed() which takes the returned value. You go to definition, and what you see:
	bool CSS1Parser::SelectorParsed( CSS1Selector* /* pSelector */, bool /*bFirst*/ )
	{
		// delete selector
		return true;
	}

  It's one of many functions in html filter which is there just for lols, but this is not the twist. You gonna ask yourself: if value from ParseSelector() just gets deleted, how could it influence the final behavior?? You'd start re-exploring the code hoping to find another global variable, but there is nothing.
  Follow the rabbit: under the Code World there is a Wonderland Of Machine Code! Fire up gdb, put breakpoint to SelectorParsed() call, and make just one little step — and you'll find there's a SvxCSS1Parser::SelectorParsed()! It has the actual code, and to my shame I don't know why it even works. It might have something to do with functions being declared as "virtual", but "class SvxCSS1Parser" is a child of CSS1Parser, and the code is executed inside the parent, and SelectorParsed() doesn't called through a pointer, rather as a local function. I guess it might be because it implicitly get called through "this" pointer…
  Interestingly though, etags navigates to the correct definition (as opposed to semantic).
• `SwCSS1Parser::StyleParsed()` is where selectors and their styles meet each other. They're stored through `InsertClass()` into a std::map `m_Classes` for further processing.

What's left, is to find where it loops over text elements (i.e. headings, paragraphs, etc), compares to selector, and applies stuff from CSS body. But I really tired, I spent much more time than it seems from the above. I've got more notes locally too, but don't think they're really relevant.
Comment 3 Konstantin Kharlamov 2017-10-01 13:59:49 UTC
I am going to try writing a new filter for writer, so may be after this is done, I could try top-down approach to html filter, being armed with the knowledge of the code components higher the stack.