Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tasks alters the DOM XPath to child tasks such that other plugins cannot get the text for those Tasks #2690

Open
4 of 7 tasks
thesamim opened this issue Mar 5, 2024 · 29 comments
Labels
help wanted Extra attention is needed scope: rendering of tasks How the plugin displays tasks (except CSS issues) type: bug Something isn't working

Comments

@thesamim
Copy link

thesamim commented Mar 5, 2024

Please check that this issue hasn't been reported before.

  • I searched previous Bug Reports didn't find any similar reports.

Expected Behavior

With Tasks enabled, another plugin should be able to get the Task Text to act on it.

Current behaviour

With Tasks enabled, another plugin cannot get the Task Text to act on it.

Steps to reproduce

Detailed instructions are in the Index file in the attached vault.
TTS Test Vault.zip

Which Operating Systems are you using?

  • Android
  • iPhone/iPad
  • Linux
  • macOS
  • Windows

Obsidian Version

v1.5.8

Tasks Plugin Version

v6.1.0

Checks

  • I have tried it with all other plugins disabled and the error still occurs

Possible solution

In

const el: HTMLElementTagNameMap[K] = document.createElement(tagName);
: the test convenience method of adding the task appears to be breaking the DOM.

@thesamim thesamim added the type: bug Something isn't working label Mar 5, 2024
@claremacrae
Copy link
Collaborator

Thanks @thesamim.

Here are the instructions extracted from the zip, to time for anyone passing by...


Instructions

login

Please see email sent separately.

monitor

Please open developer console and filter for logs with "### " to reduce the clutter.

Test Tasks

  • Parent Task link #ticktick %%[ticktick_id:: 65e789d630cc7a8b64ca5abb]%%
    • Child Task link #ticktick %%[ticktick_id:: 65e789de30cc7a8b64ca5abd]%%
      • GrandChild Task link #ticktick %%[ticktick_id:: 65e789e830cc7a8b64ca5abf]%%

Testing

Scenario 1:

With Tasks and DataView Enabled. Close the tasks.

Expected Result: In the console log, should get the Task text for all three levels..
Actual Result: Only get the Task text for the first level (Parent Task), but not the other two levels.

Scenario 2:

From Community Plugins, disable Tasks. Reopen then close the tasks.

Expected Result: In the console log, should get the Task text for all three levels..
Actual Result: We get the Task text for all three levels.

Scenario 3:

From Community Plugins, disable Dataview AND Tasks. Reopen then close the tasks.

Expected Result: In the console log, should get the Task text for all three levels..
Actual Result: We get the Task text for all three levels.

Scenario 4:

From Community Plugins, Enable Dataview AND disable Tasks. Reopen then close the tasks.

Expected Result: In the console log, should get the Task text for all three levels..
Actual Result: We get the Task text for all three levels.

Conclusion:

Tasks is changing the DOM layout, such that:

  1. Child tasks do appear is children of the parent task
  2. BUT: Tasks is modifying the DOM path such that is not possible to get back to the Task text.
  3. If there's a way to get the Task text based on the clicked element I have not found it.

@thesamim
Copy link
Author

thesamim commented Mar 5, 2024 via email

@claremacrae
Copy link
Collaborator

claremacrae commented Mar 5, 2024

Just to add that the "Login" instruction refers to going to the TickTickSync plugin and entering the credentials there.

I did Scenario 1 and got no console output at all, and not the stated expected output.

I was logged in.

image

image

image


Is this really the minimal reproduction? Why are 4 combinations required to go through?

And what has dataview got to do with it?

@claremacrae
Copy link
Collaborator

Possible solution

In

const el: HTMLElementTagNameMap[K] = document.createElement(tagName);

: the test convenience method of adding the task appears to be breaking the DOM.

Just to note that following the history back, that behaviour was introduced in 54682d4 on 28/12/2022.

The previous release was 1.20.0 - so you could try downloading that and test the theory that the making of the code testable was the cause.

This page links to the areas of the Tasks code that adjust the re-rendering of code:

https://publish.obsidian.md/tasks-contributing/Code/How+does+Tasks+handle+status+changes

One thing that it shows is that the code path is quite different depending on whether it's source, live preview or reading mode.

So one way to narrow down the cause might be to test the behaviour you observed, and see if it works or does not work in any particular modes.

@thesamim
Copy link
Author

thesamim commented Mar 5, 2024

Is this really the minimal reproduction? Why are 4 combinations required to go through?

And what has dataview got to do with it?

Trying to be thorough. The only scenarios that matter are 1 and 2.

Don't understand why you're not getting output.

Here's what I see:
image

@thesamim
Copy link
Author

thesamim commented Mar 5, 2024

The previous release was 1.20.0 - so you could try downloading that and test the theory that the making of the code testable was the cause.

Will do.

One thing that it shows is that the code path is quite different depending on whether it's source, live preview or reading mode.

Tried Source Mode and Live Preview. Made no difference to the results.

In Reading Mode: TickTickSync does not get the click event at all. Haven't dug into that yet, just rely on the periodic Sync to catch us up. But I sure would like to know the answer to that too.

@claremacrae
Copy link
Collaborator

Can you think of a simple way of recording the change in the DOM?

I did some manual testing recently by saving HTML like this... I was going it to make sure that some refactoring of untested code did not change the behaviour:

image

Maybe that gives some ideas about how you could save info from the development environment, to produce diff-able files that you could attach here...

@claremacrae
Copy link
Collaborator

I speculate that you may have encountered a consequence of one of the know limitations of Tasks:

https://publish.obsidian.md/tasks/Support+and+Help/Known+Limitations

@claremacrae
Copy link
Collaborator

Trying to be thorough. The only scenarios that matter are 1 and 2.

Same question - what has dataview got to do with it?

image

@claremacrae
Copy link
Collaborator

(This arose from #2685)

@claremacrae
Copy link
Collaborator

For my money, this would be the ideal kind of reproduction - taking Dataview and TickTickSync out of the equation - and showing what it is that Tasks breaks:

  • Here is how to see the DOM with no plugins enabled
  • And here is how to see the DOM with just the Tasks plugin enabled

And here is a diff between the two, and look, that line there is a critical diff that prevents other plugins, in the following way...

@thesamim
Copy link
Author

thesamim commented Mar 5, 2024 via email

@thesamim
Copy link
Author

thesamim commented Mar 5, 2024 via email

@claremacrae
Copy link
Collaborator

claremacrae commented Mar 5, 2024

 In essence: All that TickTickSync is doing in these scenarios is reporting results. If you can see the console log, you can see the difference in the DOM traverses. So, enabling Tasks and disabling tasks and looking at the console log accomplishes just what you’ve described.

OK, without any screenshots in the bug report I wasn't aware of that.

Unfortunately I'm not seeing any console output, so I'm a bit stumped about how to move forward.

Thank for your efforts in reporting it.


Actually, if you can create two separate screenshots showing:

  1. Just the console output when only TickTickSync is enabled
  2. Just the console output when only TickTickSync and Tasks are enabled

... would it save others from going through the reproduction steps?

@claremacrae
Copy link
Collaborator

Trivia: When replying by email, it really helps if people delete the text being replied too, for readability here.

I've been going through deleting all the quoted text, so the flow is easier to read in future... just thought I'd mention it.

@claremacrae
Copy link
Collaborator

Just to note that I haven't been involved in any of the code that adjusts the DOM - it was all written before I took over maintaining the Tasks plugin.

So if this ticket can make it clear what exactly Tasks is changing or losing from the DOM, that would affect plugin developers, it will likely also inform future ideas to address some of the other known limitations of rendering of tasks by this plugin.

I am currently firmly in "I don't know what I don't know" in this area. Hence the value for information to be clear and directly visible.

@claremacrae
Copy link
Collaborator

Actually, if you can create two separate screenshots showing:

  1. Just the console output when only TickTickSync is enabled
  2. Just the console output when only TickTickSync and Tasks are enabled

... would it save others from going through the reproduction steps?

D'oh - or even the text from the console, as then the captured information information would be useful for future searches....

@claremacrae claremacrae added the scope: rendering of tasks How the plugin displays tasks (except CSS issues) label Mar 5, 2024
@thesamim
Copy link
Author

thesamim commented Mar 6, 2024

Genius!

Testing: With and Without Tasks, click on the tasks. Save html render from both. Save the logs from both.

Finding: So, it's not an HTML structural difference apparently. It looks like the only difference is in CSS. That may cause behavioral changes. I don't know.

TTSLogs.zip

Attached files in the zip file:

  • Console logs:
  • obsidian.md-with-Tasks-Disabeled.log
  • obsidian.md-with-Tasks-Enabled.log
  • HTML files:
  • withoutTasks.html
  • WithTasks.html
  • differencereport.html

ETA: downloaded and tried with version "1.20.0". Same behavior (ie: can't get to task content from click event). So, that chunk of code probably has nothing to do with the problem. Sorry about that.

@claremacrae
Copy link
Collaborator

Finding: So, it's not an HTML structural difference apparently. It looks like the only difference is in CSS. That may cause behavioral changes. I don't know.

Good, thank you, that's really helpful to know.

I am sure that the CSS would not change the behaviour you are seeing.

Your screenshot in #2690 (comment) and your description of this issue seem to show the "DOME XPath" is involved...

Just like seeing the raw HTML was useful, "seeing" the DOM will be useful too.

So I would really appreciate it if you could see if you could find a way to save the DOM for the two scenarios - only Tasks installed, and no plugin installed.

Being able to diff those in a text editor would be super useful.

As well as making clear all the differences, it might point to an alternative implementation in Tasks, ultimately eventually leading to a solution for TickTickSync and others too...

@claremacrae
Copy link
Collaborator

claremacrae commented Mar 6, 2024

My searches for how to export and save the DOM were unsuccessful, and now I'm going to be mostly "Away from Keyboard" for a couple of days.

@claremacrae
Copy link
Collaborator

So I would really appreciate it if you could see if you could find a way to save the DOM for the two scenarios - only Tasks installed, and no plugin installed.

Being able to diff those in a text editor would be super useful.

Hi @thesamim, have you made any progress on investigations with this?

Is the ticket still needed?

@claremacrae claremacrae added the question Further information is requested label Mar 24, 2024
@thesamim
Copy link
Author

Hi @claremacrae ,

I have an idea on how to accomplish this, but have not had time to implement it.

Yes, the ticket is still needed.

@claremacrae
Copy link
Collaborator

Hi @thesamim - that’s a bit Fermat”s Last Theorem!

Please could you record the idea here so the info is not lost?

@thesamim
Copy link
Author

Hi @thesamim - that’s a bit Fermat”s Last Theorem!

Please could you record the idea here so the info is not lost?

In a vault, install the sample plugin only.
Create a document with tasks as follows

  • Task 1
    • Task 1 Child
      • Task 1 Grand Child

Using the sample plugin, add to onClickEvent a method to extract the current DOM layout. Write it to file.
Invoke the onclick event.
save the resulting file.

In the same vault, install the Tasks plugin.

Repeat.

Compare the two resulting files.
highlight the differences in layout.

@claremacrae
Copy link
Collaborator

Great - thanks.

@claremacrae claremacrae removed the question Further information is requested label Mar 31, 2024
@claremacrae
Copy link
Collaborator

No idea if this helps, but there was just an announcement on Discord of this plugin release, and it talks about inspecting the DOM tree and being useful for general development...

https://github.com/iamrecursion/obsidian-pkvs/releases/tag/1.1.0

@thesamim
Copy link
Author

thesamim commented Apr 2, 2024

Nice!!! Will explore. Thanks!

@thesamim
Copy link
Author

Pardon the long delay.

At the end of the day, all I want is to be able to get the Task text and the Task status. So if there's a different way to do that, please let me know.

Started with the sample plugin and did some "With Tasks Enabled" and "With Tasks Disabled" testing.

Methodology:
In the attached Vault, there is one file "Task Test" that has a hierarchy of tasks.

  1. Disable Tasks plugin
  2. Check each task as done. (Parent Task, Child Task, Grand Child Task)
  3. Check each task as not done. (Parent Task, Child Task, Grand Child Task)
  4. save Log.
  5. Enable Tasks plugin
  6. Repeat steps 2 - 4

Results:

  1. The HTML rendering is exactly the same. In the attached Zip File, TaskPlugin_dom.html is exactly the same as NoTaskPlugin_dom.html)
  2. The DOM parsing is the same for the top level task, but not for the sub tasks. In the attached Zip file, compare TaskPlugin_Results.log and NotaskPlugin_Results.log.

With the Tasks Plugin enabled, looking for the closest DIV, am not able to get the Task Text. Screen Shot of differences.
image

Also see differenceReport.html in the zip file for full compare.

In the zip file:

  1. Testing Vault: testingVault.zip
  2. Sample Code source code: sample.zip
  3. NoTaskPlugin_dom.html and TaskPlugin_dom.html : the html of the note. No difference.
  4. NoTaskPlugin_Results.log and TaskPlugin_Results.log: the logs from the above testing.
  5. differenceReport.html: the difference report between the two results (generated from BeyondCompare.)

obsidian-tasks_issues_2690.zip

Here are the two relevant bits of code:

Capture the whole DOM as HTML:

	const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', async (evt: MouseEvent) => {
	    // Called when the user clicks the icon.
            // console.log(document.body.innerHTML)
            let toWrite = 'E:\\temp\\dom.html';

            fs.writeFile(toWrite, document.body.innerHTML, { encoding: 'utf8' }, (err) => {
                console.log("Write Result: ", err)
            })
	});

Log relevant information when a checkbox is clicked:

	this.registerDomEvent(document, 'click', async (evt: MouseEvent) => {
            let {target} = evt;
            // const markDownView = this.app.workspace.getActiveViewOfType(MarkdownView);
            // const file = markDownView?.app.workspace.activeEditor?.file;
            // const fileName = file?.name;
            // const filepath = file?.path;


            if (target &&  target.type === 'checkbox') {
                const clickedTarget = evt.target as HTMLInputElement;
                console.log("IS: ", clickedTarget,
                    "\nClass Name",clickedTarget.className,
                    "\ntype",clickedTarget.type,
                    "\nChecked",clickedTarget.checked);

                const parent = clickedTarget.parentElement;
                console.log("Parent Element",parent)
                const grandParent = parent.parentElement;
                console.log("GrandParent",grandParent)

                target = evt.target as HTMLElement;
                const elementSearch = 'div';
                const taskElement = target.closest(elementSearch);
                if (taskElement) {
                    const lineText = taskElement.textContent;
                    if (lineText) {
                        console.log("Got Task: ", lineText);
                    } else {
                        console.log("No Line Text");
                    }
                } else {
                    console.log("Task Element not found.");
                }
            }
        });

Please let me know if you need anything else.

@claremacrae claremacrae added the help wanted Extra attention is needed label Apr 20, 2024
@claremacrae
Copy link
Collaborator

Please let me know if you need anything else.

tl;dr Yes, if you wish to pair together for a few sessions, please email me to set up some dates.

Hi @thesamim, FYI the Tasks plugin is in the fortunate position of:

  1. major pull requests coming in at a faster rate than I can handle them
  2. and currently my having at least 4 pairing sessions a week with contributors

The above are entirely driving where my time is going on the plugin right now, there is just virtually no other time available to work on it.

Additionally, as I mentioned somewhere above, fixing this is likely to require a significant re-write of the Tasks rendering code, which predates my involvement in the plugin.

This means that there is zero chance of this issue being addressed in the foreseeable future, unless anyone wishes to commit to a few weekly sessions of pairing on it with me - which would push it up the priority list for my time.

I should have some time for pairing in May - so if you would like to work on this together, over a few pairing sessions to try and understand what's going on and if we can can find a workaround, please email me to set up a schedule.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed scope: rendering of tasks How the plugin displays tasks (except CSS issues) type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants